diff options
17 files changed, 1433 insertions, 1397 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java index 178590be3b23..80ddd4a8bec1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java @@ -29,7 +29,8 @@ import com.android.systemui.qs.QSTile; import com.android.systemui.qs.QSTileView; import com.android.systemui.qs.SignalTileView; import com.android.systemui.statusbar.policy.NetworkController; -import com.android.systemui.statusbar.policy.NetworkController.DataUsageInfo; +import com.android.systemui.statusbar.policy.NetworkController.MobileDataController; +import com.android.systemui.statusbar.policy.NetworkController.MobileDataController.DataUsageInfo; import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback; /** Quick settings tile: Cellular **/ @@ -38,11 +39,13 @@ public class CellularTile extends QSTile<QSTile.SignalState> { "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity")); private final NetworkController mController; + private final MobileDataController mDataController; private final CellularDetailAdapter mDetailAdapter; public CellularTile(Host host) { super(host); mController = host.getNetworkController(); + mDataController = mController.getMobileDataController(); mDetailAdapter = new CellularDetailAdapter(); } @@ -72,7 +75,7 @@ public class CellularTile extends QSTile<QSTile.SignalState> { @Override protected void handleClick() { - if (mController.isMobileDataSupported()) { + if (mDataController.isMobileDataSupported()) { showDetail(true); } else { mHost.startSettingsActivity(CELLULAR_SETTINGS); @@ -199,7 +202,8 @@ public class CellularTile extends QSTile<QSTile.SignalState> { @Override public Boolean getToggleState() { - return mController.isMobileDataSupported() ? mController.isMobileDataEnabled() : null; + return mDataController.isMobileDataSupported() + ? mDataController.isMobileDataEnabled() : null; } @Override @@ -209,7 +213,7 @@ public class CellularTile extends QSTile<QSTile.SignalState> { @Override public void setToggleState(boolean state) { - mController.setMobileDataEnabled(state); + mDataController.setMobileDataEnabled(state); } @Override @@ -217,7 +221,7 @@ public class CellularTile extends QSTile<QSTile.SignalState> { final DataUsageDetailView v = (DataUsageDetailView) (convertView != null ? convertView : LayoutInflater.from(mContext).inflate(R.layout.data_usage, parent, false)); - final DataUsageInfo info = mController.getDataUsageInfo(); + final DataUsageInfo info = mDataController.getDataUsageInfo(); if (info == null) return v; v.bind(info); return v; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java index 7bdb58f2daa7..eb816b759c91 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java @@ -20,7 +20,6 @@ import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import android.util.AttributeSet; -import android.util.TypedValue; import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; @@ -61,7 +60,7 @@ public class DataUsageDetailView extends LinearLayout { R.dimen.qs_data_usage_text_size); } - public void bind(NetworkController.DataUsageInfo info) { + public void bind(NetworkController.MobileDataController.DataUsageInfo info) { final Resources res = mContext.getResources(); final int titleId; final long bytes; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java index 7aa884effe7a..4fb1189dee90 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java @@ -31,7 +31,8 @@ import com.android.systemui.qs.QSTile; import com.android.systemui.qs.QSTileView; import com.android.systemui.qs.SignalTileView; import com.android.systemui.statusbar.policy.NetworkController; -import com.android.systemui.statusbar.policy.NetworkController.AccessPoint; +import com.android.systemui.statusbar.policy.NetworkController.AccessPointController; +import com.android.systemui.statusbar.policy.NetworkController.AccessPointController.AccessPoint; import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback; /** Quick settings tile: Wifi **/ @@ -39,12 +40,14 @@ public class WifiTile extends QSTile<QSTile.SignalState> { private static final Intent WIFI_SETTINGS = new Intent(Settings.ACTION_WIFI_SETTINGS); private final NetworkController mController; + private final AccessPointController mWifiController; private final WifiDetailAdapter mDetailAdapter; private final QSTile.SignalState mStateBeforeClick = newTileState(); public WifiTile(Host host) { super(host); mController = host.getNetworkController(); + mWifiController = mController.getAccessPointController(); mDetailAdapter = new WifiDetailAdapter(); } @@ -62,10 +65,10 @@ public class WifiTile extends QSTile<QSTile.SignalState> { public void setListening(boolean listening) { if (listening) { mController.addNetworkSignalChangedCallback(mCallback); - mController.addAccessPointCallback(mDetailAdapter); + mWifiController.addAccessPointCallback(mDetailAdapter); } else { mController.removeNetworkSignalChangedCallback(mCallback); - mController.removeAccessPointCallback(mDetailAdapter); + mWifiController.removeAccessPointCallback(mDetailAdapter); } } @@ -87,7 +90,7 @@ public class WifiTile extends QSTile<QSTile.SignalState> { @Override protected void handleSecondaryClick() { - if (!mController.canConfigWifi()) { + if (!mWifiController.canConfigWifi()) { mHost.startSettingsActivity(new Intent(Settings.ACTION_WIFI_SETTINGS)); return; } @@ -231,7 +234,7 @@ public class WifiTile extends QSTile<QSTile.SignalState> { }; private final class WifiDetailAdapter implements DetailAdapter, - NetworkController.AccessPointCallback, QSDetailItems.Callback { + NetworkController.AccessPointController.AccessPointCallback, QSDetailItems.Callback { private QSDetailItems mItems; private AccessPoint[] mAccessPoints; @@ -261,7 +264,7 @@ public class WifiTile extends QSTile<QSTile.SignalState> { public View createDetailView(Context context, View convertView, ViewGroup parent) { if (DEBUG) Log.d(TAG, "createDetailView convertView=" + (convertView != null)); mAccessPoints = null; - mController.scanForAccessPoints(); + mWifiController.scanForAccessPoints(); fireScanStateChanged(true); mItems = QSDetailItems.convertOrInflate(context, convertView, parent); mItems.setTagSuffix("Wifi"); @@ -287,7 +290,7 @@ public class WifiTile extends QSTile<QSTile.SignalState> { if (item == null || item.tag == null) return; final AccessPoint ap = (AccessPoint) item.tag; if (!ap.isConnected) { - if (mController.connect(ap)) { + if (mWifiController.connect(ap)) { mHost.collapsePanels(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java index 9154a487e8ac..418c57f8f15c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java @@ -48,6 +48,7 @@ public class SignalClusterView private int mMobileStrengthId = 0, mMobileTypeId = 0; private boolean mIsAirplaneMode = false; private int mAirplaneIconId = 0; + private int mAirplaneContentDescription; private String mWifiDescription, mMobileDescription, mMobileTypeDescription; private boolean mIsMobileTypeIconWide; @@ -160,9 +161,10 @@ public class SignalClusterView } @Override - public void setIsAirplaneMode(boolean is, int airplaneIconId) { + public void setIsAirplaneMode(boolean is, int airplaneIconId, int contentDescription) { mIsAirplaneMode = is; mAirplaneIconId = airplaneIconId; + mAirplaneContentDescription = contentDescription; apply(); } @@ -236,6 +238,8 @@ public class SignalClusterView if (mIsAirplaneMode) { mAirplane.setImageResource(mAirplaneIconId); + mAirplane.setContentDescription(mAirplaneContentDescription != 0 ? + mContext.getString(mAirplaneContentDescription) : ""); mAirplane.setVisibility(View.VISIBLE); } else { mAirplane.setVisibility(View.GONE); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 3b2d3cb0b13c..9a1ac4949272 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -79,6 +79,7 @@ import android.provider.Settings; import android.service.notification.NotificationListenerService; import android.service.notification.NotificationListenerService.RankingMap; import android.service.notification.StatusBarNotification; +import android.text.TextUtils; import android.util.ArraySet; import android.util.DisplayMetrics; import android.util.EventLog; @@ -821,7 +822,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, signalClusterQs.setNetworkController(mNetworkController); final boolean isAPhone = mNetworkController.hasVoiceCallingFeature(); if (isAPhone) { - mNetworkController.addEmergencyLabelView(mHeader); + mNetworkController.addEmergencyListener(new NetworkControllerImpl.EmergencyListener() { + @Override + public void setEmergencyCallsOnly(boolean emergencyOnly) { + mHeader.setShowEmergencyCallsOnly(emergencyOnly); + } + }); } mCarrierLabel = (TextView)mStatusBarWindow.findViewById(R.id.carrier_label); @@ -830,13 +836,19 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (mShowCarrierInPanel) { mCarrierLabel.setVisibility(mCarrierLabelVisible ? View.VISIBLE : View.INVISIBLE); - // for mobile devices, we always show mobile connection info here (SPN/PLMN) - // for other devices, we show whatever network is connected - if (mNetworkController.hasMobileDataFeature()) { - mNetworkController.addMobileLabelView(mCarrierLabel); - } else { - mNetworkController.addCombinedLabelView(mCarrierLabel); - } + mNetworkController.addCarrierLabel(new NetworkControllerImpl.CarrierLabelListener() { + @Override + public void setCarrierLabel(String label) { + mCarrierLabel.setText(label); + if (mNetworkController.hasMobileDataFeature()) { + if (TextUtils.isEmpty(label)) { + mCarrierLabel.setVisibility(View.GONE); + } else { + mCarrierLabel.setVisibility(View.VISIBLE); + } + } + } + }); // set up the dynamic hide/show of the label // TODO: uncomment, handle this for the Stack scroller aswell diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java index 45a138610b1c..8ce608c016b5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java @@ -122,7 +122,7 @@ public class QSTileHost implements QSTile.Host { tile.userSwitch(newUserId); } mSecurity.onUserSwitched(newUserId); - mNetwork.onUserSwitched(newUserId); + mNetwork.getAccessPointController().onUserSwitched(newUserId); mObserver.register(); } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java index 0a385d72666b..6fec97e09aac 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java @@ -36,15 +36,13 @@ import android.util.ArraySet; import android.util.Log; import com.android.systemui.R; -import com.android.systemui.statusbar.policy.NetworkController.AccessPoint; -import com.android.systemui.statusbar.policy.NetworkController.AccessPointCallback; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; -public class AccessPointController { +public class AccessPointControllerImpl implements NetworkController.AccessPointController { private static final String TAG = "AccessPointController"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); @@ -69,7 +67,7 @@ public class AccessPointController { private boolean mScanning; private int mCurrentUser; - public AccessPointController(Context context) { + public AccessPointControllerImpl(Context context) { mContext = context; mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); @@ -81,25 +79,28 @@ public class AccessPointController { new UserHandle(mCurrentUser)); } - void onUserSwitched(int newUserId) { + public void onUserSwitched(int newUserId) { mCurrentUser = newUserId; } - public void addCallback(AccessPointCallback callback) { + @Override + public void addAccessPointCallback(AccessPointCallback callback) { if (callback == null || mCallbacks.contains(callback)) return; if (DEBUG) Log.d(TAG, "addCallback " + callback); mCallbacks.add(callback); mReceiver.setListening(!mCallbacks.isEmpty()); } - public void removeCallback(AccessPointCallback callback) { + @Override + public void removeAccessPointCallback(AccessPointCallback callback) { if (callback == null) return; if (DEBUG) Log.d(TAG, "removeCallback " + callback); mCallbacks.remove(callback); mReceiver.setListening(!mCallbacks.isEmpty()); } - public void scan() { + @Override + public void scanForAccessPoints() { if (mScanning) return; if (DEBUG) Log.d(TAG, "scan!"); mScanning = mWifiManager.startScan(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java index 7ac2a986c75d..b7c74e3afadf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java @@ -33,11 +33,5 @@ public class AccessibilityContentDescriptions { R.string.accessibility_wifi_three_bars, R.string.accessibility_wifi_signal_full }; - static final int[] WIMAX_CONNECTION_STRENGTH = { - R.string.accessibility_no_wimax, - R.string.accessibility_wimax_one_bar, - R.string.accessibility_wimax_two_bars, - R.string.accessibility_wimax_three_bars, - R.string.accessibility_wimax_signal_full - }; + static final int WIFI_NO_CONNECTION = R.string.accessibility_no_wifi; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataControllerImpl.java index 33d68bf37f09..20f0a83d38b1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataControllerImpl.java @@ -38,12 +38,10 @@ import android.text.format.DateUtils; import android.text.format.Time; import android.util.Log; -import com.android.systemui.statusbar.policy.NetworkController.DataUsageInfo; - import java.util.Date; import java.util.Locale; -public class MobileDataController { +public class MobileDataControllerImpl implements NetworkController.MobileDataController { private static final String TAG = "MobileDataController"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); @@ -61,8 +59,9 @@ public class MobileDataController { private INetworkStatsSession mSession; private Callback mCallback; + private NetworkControllerImpl mNetworkController; - public MobileDataController(Context context) { + public MobileDataControllerImpl(Context context) { mContext = context; mTelephonyManager = TelephonyManager.from(context); mConnectivityManager = ConnectivityManager.from(context); @@ -71,6 +70,10 @@ public class MobileDataController { mPolicyManager = NetworkPolicyManager.from(mContext); } + public void setNetworkController(NetworkControllerImpl networkController) { + mNetworkController = networkController; + } + private INetworkStatsSession getSession() { if (mSession == null) { try { @@ -155,6 +158,9 @@ public class MobileDataController { } else { usage.warningLevel = DEFAULT_WARNING_LEVEL; } + if (usage != null) { + usage.carrier = mNetworkController.getMobileNetworkName(); + } return usage; } catch (RemoteException e) { return warn("remote call failed"); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index bb29d01e2557..b024f58cbd27 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -22,6 +22,8 @@ public interface NetworkController { void addNetworkSignalChangedCallback(NetworkSignalChangedCallback cb); void removeNetworkSignalChangedCallback(NetworkSignalChangedCallback cb); void setWifiEnabled(boolean enabled); + AccessPointController getAccessPointController(); + MobileDataController getMobileDataController(); public interface NetworkSignalChangedCallback { void onWifiSignalChanged(boolean enabled, boolean connected, int wifiSignalIconId, @@ -36,38 +38,50 @@ public interface NetworkController { void onMobileDataEnabled(boolean enabled); } - void addAccessPointCallback(AccessPointCallback callback); - void removeAccessPointCallback(AccessPointCallback callback); - void scanForAccessPoints(); - boolean connect(AccessPoint ap); - boolean isMobileDataSupported(); - boolean isMobileDataEnabled(); - void setMobileDataEnabled(boolean enabled); - DataUsageInfo getDataUsageInfo(); - boolean canConfigWifi(); - void onUserSwitched(int newUserId); + /** + * Tracks changes in access points. Allows listening for changes, scanning for new APs, + * and connecting to new ones. + */ + public interface AccessPointController { + void addAccessPointCallback(AccessPointCallback callback); + void removeAccessPointCallback(AccessPointCallback callback); + void scanForAccessPoints(); + boolean connect(AccessPoint ap); + boolean canConfigWifi(); + void onUserSwitched(int newUserId); - public interface AccessPointCallback { - void onAccessPointsChanged(AccessPoint[] accessPoints); - } + public interface AccessPointCallback { + void onAccessPointsChanged(AccessPoint[] accessPoints); + } - public static class AccessPoint { - public static final int NO_NETWORK = -1; // see WifiManager + public static class AccessPoint { + public static final int NO_NETWORK = -1; // see WifiManager - public int networkId; - public int iconId; - public String ssid; - public boolean isConnected; - public boolean isConfigured; - public boolean hasSecurity; - public int level; // 0 - 5 + public int networkId; + public int iconId; + public String ssid; + public boolean isConnected; + public boolean isConfigured; + public boolean hasSecurity; + public int level; // 0 - 5 + } } - public static class DataUsageInfo { - public String carrier; - public String period; - public long limitLevel; - public long warningLevel; - public long usageLevel; + /** + * Tracks mobile data support and usage. + */ + public interface MobileDataController { + boolean isMobileDataSupported(); + boolean isMobileDataEnabled(); + void setMobileDataEnabled(boolean enabled); + DataUsageInfo getDataUsageInfo(); + + public static class DataUsageInfo { + public String carrier; + public String period; + public long limitLevel; + public long warningLevel; + public long usageLevel; + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index 07762a4604c0..5a97c75e313b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -26,7 +26,6 @@ import android.net.NetworkInfo; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; -import android.net.wimax.WimaxManagerConstants; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; @@ -37,9 +36,8 @@ import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.TelephonyManager; +import android.text.format.DateFormat; import android.util.Log; -import android.view.View; -import android.widget.TextView; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.IccCardConstants; @@ -48,130 +46,66 @@ import com.android.internal.telephony.cdma.EriInfo; import com.android.internal.util.AsyncChannel; import com.android.systemui.DemoMode; import com.android.systemui.R; -import com.android.systemui.statusbar.phone.StatusBarHeaderView; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; +import java.util.Objects; /** Platform implementation of the network controller. **/ public class NetworkControllerImpl extends BroadcastReceiver implements NetworkController, DemoMode { // debug - static final String TAG = "StatusBar.NetworkController"; - static final boolean DEBUG = false; - static final boolean CHATTY = false; // additional diagnostics, but not logspew - - // telephony - boolean mHspaDataDistinguishable; - final TelephonyManager mPhone; - boolean mDataConnected; - IccCardConstants.State mSimState = IccCardConstants.State.READY; - int mPhoneState = TelephonyManager.CALL_STATE_IDLE; - int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN; - int mDataState = TelephonyManager.DATA_DISCONNECTED; - int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE; - ServiceState mServiceState; - SignalStrength mSignalStrength; - int[] mDataIconList = TelephonyIcons.DATA_G[0]; - String mNetworkName; - String mNetworkNameDefault; - String mNetworkNameSeparator; - int mPhoneSignalIconId; - int mQSPhoneSignalIconId; - int mDataDirectionIconId; // data + data direction on phones - int mDataSignalIconId; - int mDataTypeIconId; - int mQSDataTypeIconId; - int mAirplaneIconId; - boolean mDataActive; - boolean mNoSim; - int mLastSignalLevel; - boolean mShowPhoneRSSIForData = false; - boolean mShowAtLeastThreeGees = false; - boolean mAlwaysShowCdmaRssi = false; - - String mContentDescriptionPhoneSignal; - String mContentDescriptionWifi; - String mContentDescriptionWimax; - String mContentDescriptionCombinedSignal; - String mContentDescriptionDataType; - - // wifi - final WifiManager mWifiManager; - AsyncChannel mWifiChannel; - boolean mWifiEnabled, mWifiConnected; - int mWifiRssi, mWifiLevel; - String mWifiSsid; - int mWifiIconId = 0; - int mQSWifiIconId = 0; - int mWifiActivity = WifiManager.DATA_ACTIVITY_NONE; + static final String TAG = "NetworkController"; + static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + // additional diagnostics, but not logspew + static final boolean CHATTY = Log.isLoggable(TAG + ".Chat", Log.DEBUG); + // Save the previous states of all SignalController state info. + static final boolean RECORD_HISTORY = true; + // How many to save, must be a power of 2. + static final int HISTORY_SIZE = 16; + + private static final int INET_CONDITION_THRESHOLD = 50; + + private final Context mContext; + private final TelephonyManager mPhone; + private final WifiManager mWifiManager; + private final ConnectivityManager mConnectivityManager; + private final boolean mHasMobileDataFeature; + + // Subcontrollers. + @VisibleForTesting + final WifiSignalController mWifiSignalController; + @VisibleForTesting + final MobileSignalController mMobileSignalController; + private final AccessPointController mAccessPoints; + private final MobileDataControllerImpl mMobileDataController; // bluetooth private boolean mBluetoothTethered = false; - private int mBluetoothTetherIconId = - com.android.internal.R.drawable.stat_sys_tether_bluetooth; - - //wimax - private boolean mWimaxSupported = false; - private boolean mIsWimaxEnabled = false; - private boolean mWimaxConnected = false; - private boolean mWimaxIdle = false; - private int mWimaxIconId = 0; - private int mWimaxSignal = 0; - private int mWimaxState = 0; - private int mWimaxExtraState = 0; // data connectivity (regardless of state, can we access the internet?) // state of inet connection - 0 not connected, 100 connected private boolean mConnected = false; private int mConnectedNetworkType = ConnectivityManager.TYPE_NONE; private String mConnectedNetworkTypeName; - private int mLastConnectedNetworkType = ConnectivityManager.TYPE_NONE; - - private int mInetCondition = 0; - private int mLastInetCondition = 0; - private static final int INET_CONDITION_THRESHOLD = 50; + private boolean mInetCondition; // Used for Logging and demo. + // States that don't belong to a subcontroller. private boolean mAirplaneMode = false; - private boolean mLastAirplaneMode = true; - private Locale mLocale = null; - private Locale mLastLocale = null; - - // our ui - Context mContext; - ArrayList<TextView> mCombinedLabelViews = new ArrayList<TextView>(); - ArrayList<TextView> mMobileLabelViews = new ArrayList<TextView>(); - ArrayList<TextView> mWifiLabelViews = new ArrayList<TextView>(); - ArrayList<StatusBarHeaderView> mEmergencyViews = new ArrayList<>(); - ArrayList<SignalCluster> mSignalClusters = new ArrayList<SignalCluster>(); - ArrayList<NetworkSignalChangedCallback> mSignalsChangedCallbacks = - new ArrayList<NetworkSignalChangedCallback>(); - int mLastPhoneSignalIconId = -1; - int mLastDataDirectionIconId = -1; - int mLastWifiIconId = -1; - int mLastWimaxIconId = -1; - int mLastCombinedSignalIconId = -1; - int mLastDataTypeIconId = -1; - String mLastCombinedLabel = ""; - private boolean mHasMobileDataFeature; - - boolean mDataAndWifiStacked = false; - - public interface SignalCluster { - void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription); - void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon, - String contentDescription, String typeContentDescription, boolean isTypeIconWide); - void setIsAirplaneMode(boolean is, int airplaneIcon); - } - - private final AccessPointController mAccessPoints; - private final MobileDataController mMobileDataController; - private final ConnectivityManager mConnectivityManager; + // All the callbacks. + private ArrayList<EmergencyListener> mEmergencyListeners = new ArrayList<EmergencyListener>(); + private ArrayList<CarrierLabelListener> mCarrierListeners = + new ArrayList<CarrierLabelListener>(); + private ArrayList<SignalCluster> mSignalClusters = new ArrayList<SignalCluster>(); + private ArrayList<NetworkSignalChangedCallback> mSignalsChangedCallbacks = + new ArrayList<NetworkSignalChangedCallback>(); /** * Construct this controller object and register for updates. @@ -180,70 +114,50 @@ public class NetworkControllerImpl extends BroadcastReceiver this(context, (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE), (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE), (WifiManager) context.getSystemService(Context.WIFI_SERVICE), - new AccessPointController(context), new MobileDataController(context)); + Config.readConfig(context), new AccessPointControllerImpl(context), + new MobileDataControllerImpl(context)); registerListeners(); } @VisibleForTesting NetworkControllerImpl(Context context, ConnectivityManager connectivityManager, - TelephonyManager telephonyManager, WifiManager wifiManager, - AccessPointController accessPointController, - MobileDataController mobileDataController) { + TelephonyManager telephonyManager, WifiManager wifiManager, Config config, + AccessPointControllerImpl accessPointController, + MobileDataControllerImpl mobileDataController) { mContext = context; - final Resources res = context.getResources(); mConnectivityManager = connectivityManager; mHasMobileDataFeature = mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE); - mShowPhoneRSSIForData = res.getBoolean(R.bool.config_showPhoneRSSIForData); - mShowAtLeastThreeGees = res.getBoolean(R.bool.config_showMin3G); - mAlwaysShowCdmaRssi = res.getBoolean( - com.android.internal.R.bool.config_alwaysUseCdmaRssi); - - // set up the default wifi icon, used when no radios have ever appeared - updateWifiIcons(); - updateWimaxIcons(); - // telephony mPhone = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); - mHspaDataDistinguishable = mContext.getResources().getBoolean( - R.bool.config_hspa_data_distinguishable); - mNetworkNameSeparator = mContext.getString(R.string.status_bar_network_name_separator); - mNetworkNameDefault = mContext.getString( - com.android.internal.R.string.lockscreen_carrier_default); - mNetworkName = mNetworkNameDefault; // wifi mWifiManager = wifiManager; - Handler handler = new WifiHandler(); - mWifiChannel = new AsyncChannel(); - Messenger wifiMessenger = mWifiManager.getWifiServiceMessenger(); - if (wifiMessenger != null) { - mWifiChannel.connect(mContext, handler, wifiMessenger); - } - - // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it - updateAirplaneMode(); - mLastLocale = mContext.getResources().getConfiguration().locale; + mLocale = mContext.getResources().getConfiguration().locale; mAccessPoints = accessPointController; mMobileDataController = mobileDataController; - mMobileDataController.setCallback(new MobileDataController.Callback() { + mMobileDataController.setNetworkController(this); + // TODO: Find a way to move this into MobileDataController. + mMobileDataController.setCallback(new MobileDataControllerImpl.Callback() { @Override public void onMobileDataEnabled(boolean enabled) { notifyMobileDataEnabled(enabled); } }); + mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature, + mSignalsChangedCallbacks, mSignalClusters, this); + mMobileSignalController = new MobileSignalController(mContext, config, + mHasMobileDataFeature, mPhone, mSignalsChangedCallbacks, mSignalClusters, this); + + // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it + updateAirplaneMode(true); } private void registerListeners() { - mPhone.listen(mPhoneStateListener, - PhoneStateListener.LISTEN_SERVICE_STATE - | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS - | PhoneStateListener.LISTEN_CALL_STATE - | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE - | PhoneStateListener.LISTEN_DATA_ACTIVITY); + mMobileSignalController.registerListener(); // broadcasts IntentFilter filter = new IntentFilter(); @@ -256,29 +170,38 @@ public class NetworkControllerImpl extends BroadcastReceiver filter.addAction(ConnectivityManager.INET_CONDITION_ACTION); filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); - mWimaxSupported = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_wimaxEnabled); - if(mWimaxSupported) { - filter.addAction(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION); - filter.addAction(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION); - filter.addAction(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION); - } mContext.registerReceiver(this, filter); } + private void unregisterListeners() { + mMobileSignalController.unregisterListener(); + mContext.unregisterReceiver(this); + } + @Override - public boolean canConfigWifi() { - return mAccessPoints.canConfigWifi(); + public AccessPointController getAccessPointController() { + return mAccessPoints; } @Override - public void onUserSwitched(int newUserId) { - mAccessPoints.onUserSwitched(newUserId); + public MobileDataController getMobileDataController() { + return mMobileDataController; + } + + public void addEmergencyListener(EmergencyListener listener) { + mEmergencyListeners.add(listener); + refreshCarrierLabel(); + } + + public void addCarrierLabel(CarrierLabelListener listener) { + mCarrierListeners.add(listener); + refreshCarrierLabel(); } private void notifyMobileDataEnabled(boolean enabled) { - for (NetworkSignalChangedCallback cb : mSignalsChangedCallbacks) { - cb.onMobileDataEnabled(enabled); + int length = mSignalsChangedCallbacks.size(); + for (int i = 0; i < length; i++) { + mSignalsChangedCallbacks.get(i).onMobileDataEnabled(enabled); } } @@ -290,34 +213,40 @@ public class NetworkControllerImpl extends BroadcastReceiver return mPhone.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE; } - public boolean isEmergencyOnly() { - return (mServiceState != null && mServiceState.isEmergencyOnly()); - } - - public void addCombinedLabelView(TextView v) { - mCombinedLabelViews.add(v); + public String getMobileNetworkName() { + return mMobileSignalController.mCurrentState.networkName; } - public void addMobileLabelView(TextView v) { - mMobileLabelViews.add(v); + public boolean isEmergencyOnly() { + return mMobileSignalController.isEmergencyOnly(); } - public void addWifiLabelView(TextView v) { - mWifiLabelViews.add(v); - } + /** + * Emergency status may have changed (triggered by MobileSignalController), + * so we should recheck and send out the state to listeners. + */ + void recalculateEmergency() { + final boolean emergencyOnly = isEmergencyOnly(); - public void addEmergencyLabelView(StatusBarHeaderView v) { - mEmergencyViews.add(v); + int length = mEmergencyListeners.size(); + for (int i = 0; i < length; i++) { + mEmergencyListeners.get(i).setEmergencyCallsOnly(emergencyOnly); + } } public void addSignalCluster(SignalCluster cluster) { mSignalClusters.add(cluster); - refreshSignalCluster(cluster); + cluster.setIsAirplaneMode(mAirplaneMode, TelephonyIcons.FLIGHT_MODE_ICON, + R.string.accessibility_airplane_mode); + mWifiSignalController.notifyListeners(); + mMobileSignalController.notifyListeners(); } public void addNetworkSignalChangedCallback(NetworkSignalChangedCallback cb) { mSignalsChangedCallbacks.add(cb); - notifySignalsChangedCallbacks(cb); + cb.onAirplaneModeChanged(mAirplaneMode); + mWifiSignalController.notifyListeners(); + mMobileSignalController.notifyListeners(); } public void removeNetworkSignalChangedCallback(NetworkSignalChangedCallback cb) { @@ -325,26 +254,6 @@ public class NetworkControllerImpl extends BroadcastReceiver } @Override - public void addAccessPointCallback(AccessPointCallback callback) { - mAccessPoints.addCallback(callback); - } - - @Override - public void removeAccessPointCallback(AccessPointCallback callback) { - mAccessPoints.removeCallback(callback); - } - - @Override - public void scanForAccessPoints() { - mAccessPoints.scan(); - } - - @Override - public boolean connect(AccessPoint ap) { - return mAccessPoints.connect(ap); - } - - @Override public void setWifiEnabled(final boolean enabled) { new AsyncTask<Void, Void, Void>() { @Override @@ -352,7 +261,7 @@ public class NetworkControllerImpl extends BroadcastReceiver // Disable tethering if enabling Wifi final int wifiApState = mWifiManager.getWifiApState(); if (enabled && ((wifiApState == WifiManager.WIFI_AP_STATE_ENABLING) || - (wifiApState == WifiManager.WIFI_AP_STATE_ENABLED))) { + (wifiApState == WifiManager.WIFI_AP_STATE_ENABLED))) { mWifiManager.setWifiApEnabled(null, false); } @@ -363,1275 +272,1250 @@ public class NetworkControllerImpl extends BroadcastReceiver } @Override - public DataUsageInfo getDataUsageInfo() { - final DataUsageInfo info = mMobileDataController.getDataUsageInfo(); - if (info != null) { - info.carrier = mNetworkName; + public void onReceive(Context context, Intent intent) { + if (CHATTY) { + Log.d(TAG, "onReceive: intent=" + intent); } - return info; + final String action = intent.getAction(); + if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE) || + action.equals(ConnectivityManager.INET_CONDITION_ACTION)) { + updateConnectivity(intent); + refreshCarrierLabel(); + } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { + refreshLocale(); + refreshCarrierLabel(); + } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { + refreshLocale(); + updateAirplaneMode(false); + refreshCarrierLabel(); + } + mWifiSignalController.handleBroadcast(intent); + mMobileSignalController.handleBroadcast(intent); } - @Override - public boolean isMobileDataSupported() { - return mMobileDataController.isMobileDataSupported(); + private void updateAirplaneMode(boolean force) { + boolean airplaneMode = (Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.AIRPLANE_MODE_ON, 0) == 1); + if (airplaneMode != mAirplaneMode || force) { + mAirplaneMode = airplaneMode; + mMobileSignalController.setAirplaneMode(mAirplaneMode); + notifyAirplaneCallbacks(); + refreshCarrierLabel(); + } } - @Override - public boolean isMobileDataEnabled() { - return mMobileDataController.isMobileDataEnabled(); + private void refreshLocale() { + Locale current = mContext.getResources().getConfiguration().locale; + if (current.equals(mLocale)) { + mLocale = current; + notifyAllListeners(); + } } - @Override - public void setMobileDataEnabled(boolean enabled) { - mMobileDataController.setMobileDataEnabled(enabled); + /** + * Turns inet condition into a boolean indexing for a specific network. + * returns 0 for bad connectivity on this network. + * returns 1 for good connectivity on this network. + */ + private int inetConditionForNetwork(int networkType, boolean inetCondition) { + return (inetCondition && mConnectedNetworkType == networkType) ? 1 : 0; } - private boolean isTypeIconWide(int iconId) { - return TelephonyIcons.ICON_LTE == iconId || TelephonyIcons.ICON_1X == iconId - || TelephonyIcons.ICON_3G == iconId || TelephonyIcons.ICON_4G == iconId; + private void notifyAllListeners() { + // Something changed, trigger everything! + notifyAirplaneCallbacks(); + mMobileSignalController.notifyListeners(); + mWifiSignalController.notifyListeners(); } - private boolean isQsTypeIconWide(int iconId) { - return TelephonyIcons.QS_ICON_LTE == iconId || TelephonyIcons.QS_ICON_1X == iconId - || TelephonyIcons.QS_ICON_3G == iconId || TelephonyIcons.QS_ICON_4G == iconId; + private void notifyAirplaneCallbacks() { + int length = mSignalClusters.size(); + for (int i = 0; i < length; i++) { + mSignalClusters.get(i).setIsAirplaneMode(mAirplaneMode, TelephonyIcons.FLIGHT_MODE_ICON, + R.string.accessibility_airplane_mode); + } + // update QS + int signalsChangedLength = mSignalsChangedCallbacks.size(); + for (int i = 0; i < signalsChangedLength; i++) { + mSignalsChangedCallbacks.get(i).onAirplaneModeChanged(mAirplaneMode); + } } - public void refreshSignalCluster(SignalCluster cluster) { - if (mDemoMode) return; - cluster.setWifiIndicators( - // only show wifi in the cluster if connected or if wifi-only - mWifiEnabled && (mWifiConnected || !mHasMobileDataFeature), - mWifiIconId, - mContentDescriptionWifi); - - if (mIsWimaxEnabled && mWimaxConnected) { - // wimax is special - cluster.setMobileDataIndicators( - true, - mAlwaysShowCdmaRssi ? mPhoneSignalIconId : mWimaxIconId, - mDataTypeIconId, - mContentDescriptionWimax, - mContentDescriptionDataType, - false /* isTypeIconWide */ ); - } else { - // normal mobile data - cluster.setMobileDataIndicators( - mHasMobileDataFeature, - mShowPhoneRSSIForData ? mPhoneSignalIconId : mDataSignalIconId, - mDataTypeIconId, - mContentDescriptionPhoneSignal, - mContentDescriptionDataType, - isTypeIconWide(mDataTypeIconId)); - } - cluster.setIsAirplaneMode(mAirplaneMode, mAirplaneIconId); - } + /** + * Update the Inet conditions and what network we are connected to. + */ + private void updateConnectivity(Intent intent) { + final NetworkInfo info = mConnectivityManager.getActiveNetworkInfo(); - void notifySignalsChangedCallbacks(NetworkSignalChangedCallback cb) { - // only show wifi in the cluster if connected or if wifi-only - boolean wifiEnabled = mWifiEnabled && (mWifiConnected || !mHasMobileDataFeature); - String wifiDesc = wifiEnabled ? - mWifiSsid : null; - boolean wifiIn = wifiEnabled && mWifiSsid != null - && (mWifiActivity == WifiManager.DATA_ACTIVITY_INOUT - || mWifiActivity == WifiManager.DATA_ACTIVITY_IN); - boolean wifiOut = wifiEnabled && mWifiSsid != null - && (mWifiActivity == WifiManager.DATA_ACTIVITY_INOUT - || mWifiActivity == WifiManager.DATA_ACTIVITY_OUT); - cb.onWifiSignalChanged(mWifiEnabled, mWifiConnected, mQSWifiIconId, wifiIn, wifiOut, - mContentDescriptionWifi, wifiDesc); - - boolean mobileIn = mDataConnected && (mDataActivity == TelephonyManager.DATA_ACTIVITY_INOUT - || mDataActivity == TelephonyManager.DATA_ACTIVITY_IN); - boolean mobileOut = mDataConnected && (mDataActivity == TelephonyManager.DATA_ACTIVITY_INOUT - || mDataActivity == TelephonyManager.DATA_ACTIVITY_OUT); - if (isEmergencyOnly()) { - cb.onMobileDataSignalChanged(false, mQSPhoneSignalIconId, - mContentDescriptionPhoneSignal, mQSDataTypeIconId, mobileIn, mobileOut, - mContentDescriptionDataType, null, mNoSim, isQsTypeIconWide(mQSDataTypeIconId)); + // Are we connected at all, by any interface? + mConnected = info != null && info.isConnected(); + if (mConnected) { + mConnectedNetworkType = info.getType(); + mConnectedNetworkTypeName = info.getTypeName(); } else { - if (mIsWimaxEnabled && mWimaxConnected) { - // Wimax is special - cb.onMobileDataSignalChanged(true, mQSPhoneSignalIconId, - mContentDescriptionPhoneSignal, mQSDataTypeIconId, mobileIn, mobileOut, - mContentDescriptionDataType, mNetworkName, mNoSim, - isQsTypeIconWide(mQSDataTypeIconId)); - } else { - // Normal mobile data - cb.onMobileDataSignalChanged(mHasMobileDataFeature, mQSPhoneSignalIconId, - mContentDescriptionPhoneSignal, mQSDataTypeIconId, mobileIn, mobileOut, - mContentDescriptionDataType, mNetworkName, mNoSim, - isQsTypeIconWide(mQSDataTypeIconId)); - } + mConnectedNetworkType = ConnectivityManager.TYPE_NONE; + mConnectedNetworkTypeName = null; } - cb.onAirplaneModeChanged(mAirplaneMode); - } - public void setStackedMode(boolean stacked) { - mDataAndWifiStacked = true; - } + int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0); - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (action.equals(WifiManager.RSSI_CHANGED_ACTION) - || action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION) - || action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { - updateWifiState(intent); - refreshViews(); - } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) { - updateSimState(intent); - updateDataIcon(); - refreshViews(); - } else if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) { - updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false), - intent.getStringExtra(TelephonyIntents.EXTRA_SPN), - intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false), - intent.getStringExtra(TelephonyIntents.EXTRA_PLMN)); - refreshViews(); - } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE) || - action.equals(ConnectivityManager.INET_CONDITION_ACTION)) { - updateConnectivity(intent); - refreshViews(); - } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { - refreshLocale(); - refreshViews(); - } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { - refreshLocale(); - updateAirplaneMode(); - refreshViews(); - } else if (action.equals(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION) || - action.equals(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION) || - action.equals(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION)) { - updateWimaxState(intent); - refreshViews(); + if (CHATTY) { + Log.d(TAG, "updateConnectivity: networkInfo=" + info); + Log.d(TAG, "updateConnectivity: connectionStatus=" + connectionStatus); } + + mInetCondition = connectionStatus > INET_CONDITION_THRESHOLD; + + if (info != null && info.getType() == ConnectivityManager.TYPE_BLUETOOTH) { + mBluetoothTethered = info.isConnected(); + } else { + mBluetoothTethered = false; + } + + // We want to update all the icons, all at once, for any condition change + mMobileSignalController.setInetCondition(mInetCondition ? 1 : 0, + inetConditionForNetwork(mMobileSignalController.getNetworkType(), mInetCondition)); + mWifiSignalController.setInetCondition( + inetConditionForNetwork(mWifiSignalController.getNetworkType(), mInetCondition)); } + /** + * Recalculate and update the carrier label. + */ + void refreshCarrierLabel() { + Context context = mContext; - // ===== Telephony ============================================================== + WifiSignalController.WifiState wifiState = mWifiSignalController.getState(); + MobileSignalController.MobileState mobileState = mMobileSignalController.getState(); + String label = mMobileSignalController.getLabel("", mConnected, mHasMobileDataFeature); - PhoneStateListener mPhoneStateListener = new PhoneStateListener() { - @Override - public void onSignalStrengthsChanged(SignalStrength signalStrength) { - if (DEBUG) { - Log.d(TAG, "onSignalStrengthsChanged signalStrength=" + signalStrength + - ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel()))); - } - mSignalStrength = signalStrength; - updateTelephonySignalStrength(); - refreshViews(); + // TODO Simplify this ugliness, some of the flows below shouldn't be possible anymore + // but stay for the sake of history. + if (mBluetoothTethered && !mHasMobileDataFeature) { + label = mContext.getString(R.string.bluetooth_tethered); } - @Override - public void onServiceStateChanged(ServiceState state) { - if (DEBUG) { - Log.d(TAG, "onServiceStateChanged voiceState=" + state.getVoiceRegState() - + " dataState=" + state.getDataRegState()); - } - mServiceState = state; - updateTelephonySignalStrength(); - updateDataNetType(); - updateDataIcon(); - refreshViews(); + final boolean ethernetConnected = + (mConnectedNetworkType == ConnectivityManager.TYPE_ETHERNET); + if (ethernetConnected && !mHasMobileDataFeature) { + label = context.getString(R.string.ethernet_label); } - @Override - public void onCallStateChanged(int state, String incomingNumber) { - if (DEBUG) { - Log.d(TAG, "onCallStateChanged state=" + state); - } - // In cdma, if a voice call is made, RSSI should switch to 1x. - if (isCdma()) { - updateTelephonySignalStrength(); - refreshViews(); + if (mAirplaneMode && (!mobileState.connected && !mobileState.isEmergency)) { + // combined values from connected wifi take precedence over airplane mode + if (wifiState.connected && mHasMobileDataFeature) { + // Suppress "No internet connection." from mobile if wifi connected. + label = ""; + } else { + if (!mHasMobileDataFeature) { + label = context.getString( + R.string.status_bar_settings_signal_meter_disconnected); + } } + } else if (!mobileState.dataConnected && !wifiState.connected && !mBluetoothTethered && + !ethernetConnected && !mHasMobileDataFeature) { + // Pretty much no connection. + label = context.getString(R.string.status_bar_settings_signal_meter_disconnected); } - @Override - public void onDataConnectionStateChanged(int state, int networkType) { - if (DEBUG) { - Log.d(TAG, "onDataConnectionStateChanged: state=" + state - + " type=" + networkType); - } - mDataState = state; - mDataNetType = networkType; - updateDataNetType(); - updateDataIcon(); - refreshViews(); + // for mobile devices, we always show mobile connection info here (SPN/PLMN) + // for other devices, we show whatever network is connected + // This is determined above by references to mHasMobileDataFeature. + int length = mCarrierListeners.size(); + for (int i = 0; i < length; i++) { + mCarrierListeners.get(i).setCarrierLabel(label); } + } - @Override - public void onDataActivity(int direction) { - if (DEBUG) { - Log.d(TAG, "onDataActivity: direction=" + direction); - } - mDataActivity = direction; - updateDataIcon(); - refreshViews(); - } - }; + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + pw.println("NetworkController state:"); + pw.println(String.format(" %s network type %d (%s)", + mConnected ? "CONNECTED" : "DISCONNECTED", + mConnectedNetworkType, mConnectedNetworkTypeName)); + pw.println(" - telephony ------"); + pw.print(" hasVoiceCallingFeature()="); + pw.println(hasVoiceCallingFeature()); - private final void updateSimState(Intent intent) { - String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); - if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) { - mSimState = IccCardConstants.State.ABSENT; - } - else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) { - mSimState = IccCardConstants.State.READY; - } - else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) { - final String lockedReason = - intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON); - if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) { - mSimState = IccCardConstants.State.PIN_REQUIRED; + pw.println(" - Bluetooth ----"); + pw.print(" mBtReverseTethered="); + pw.println(mBluetoothTethered); + + pw.println(" - connectivity ------"); + pw.print(" mInetCondition="); + pw.println(mInetCondition); + pw.print(" mAirplaneMode="); + pw.println(mAirplaneMode); + pw.print(" mLocale="); + pw.println(mLocale); + + mMobileSignalController.dump(pw); + mWifiSignalController.dump(pw); + } + + private boolean mDemoMode; + private int mDemoInetCondition; + private WifiSignalController.WifiState mDemoWifiState; + private MobileSignalController.MobileState mDemoMobileState; + + @Override + public void dispatchDemoCommand(String command, Bundle args) { + if (!mDemoMode && command.equals(COMMAND_ENTER)) { + if (DEBUG) Log.d(TAG, "Entering demo mode"); + unregisterListeners(); + mDemoMode = true; + mDemoInetCondition = mInetCondition ? 1 : 0; + mDemoWifiState = mWifiSignalController.getState(); + mDemoMobileState = mMobileSignalController.getState(); + } else if (mDemoMode && command.equals(COMMAND_EXIT)) { + if (DEBUG) Log.d(TAG, "Exiting demo mode"); + mDemoMode = false; + mWifiSignalController.resetLastState(); + mMobileSignalController.resetLastState(); + registerListeners(); + notifyAllListeners(); + refreshCarrierLabel(); + } else if (mDemoMode && command.equals(COMMAND_NETWORK)) { + String airplane = args.getString("airplane"); + if (airplane != null) { + boolean show = airplane.equals("show"); + int length = mSignalClusters.size(); + for (int i = 0; i < length; i++) { + mSignalClusters.get(i).setIsAirplaneMode(show, TelephonyIcons.FLIGHT_MODE_ICON, + R.string.accessibility_airplane_mode); + } } - else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) { - mSimState = IccCardConstants.State.PUK_REQUIRED; + String fully = args.getString("fully"); + if (fully != null) { + mDemoInetCondition = Boolean.parseBoolean(fully) ? 1 : 0; + mWifiSignalController.setInetCondition(mDemoInetCondition); + mMobileSignalController.setInetCondition(mDemoInetCondition, mDemoInetCondition); + } + String wifi = args.getString("wifi"); + if (wifi != null) { + boolean show = wifi.equals("show"); + String level = args.getString("level"); + if (level != null) { + mDemoWifiState.level = level.equals("null") ? -1 + : Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1); + mDemoWifiState.connected = mDemoWifiState.level >= 0; + } + mDemoWifiState.enabled = show; + mWifiSignalController.notifyListeners(); } - else { - mSimState = IccCardConstants.State.NETWORK_LOCKED; + String mobile = args.getString("mobile"); + if (mobile != null) { + boolean show = mobile.equals("show"); + String datatype = args.getString("datatype"); + if (datatype != null) { + mDemoMobileState.iconGroup = + datatype.equals("1x") ? TelephonyIcons.ONE_X : + datatype.equals("3g") ? TelephonyIcons.THREE_G : + datatype.equals("4g") ? TelephonyIcons.FOUR_G : + datatype.equals("e") ? TelephonyIcons.E : + datatype.equals("g") ? TelephonyIcons.G : + datatype.equals("h") ? TelephonyIcons.H : + datatype.equals("lte") ? TelephonyIcons.LTE : + datatype.equals("roam") ? TelephonyIcons.ROAMING : + TelephonyIcons.UNKNOWN; + } + int[][] icons = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH; + String level = args.getString("level"); + if (level != null) { + mDemoMobileState.level = level.equals("null") ? -1 + : Math.min(Integer.parseInt(level), icons[0].length - 1); + mDemoMobileState.connected = mDemoMobileState.level >= 0; + } + mDemoMobileState.enabled = show; + mMobileSignalController.notifyListeners(); } - } else { - mSimState = IccCardConstants.State.UNKNOWN; + refreshCarrierLabel(); } - if (DEBUG) Log.d(TAG, "updateSimState: mSimState=" + mSimState); - } - - private boolean isCdma() { - return (mSignalStrength != null) && !mSignalStrength.isGsm(); } - private boolean hasService() { - boolean retVal; - if (mServiceState != null) { - // Consider the device to be in service if either voice or data service is available. - // Some SIM cards are marketed as data-only and do not support voice service, and on - // these SIM cards, we want to show signal bars for data service as well as the "no - // service" or "emergency calls only" text that indicates that voice is not available. - switch(mServiceState.getVoiceRegState()) { - case ServiceState.STATE_POWER_OFF: - retVal = false; - break; - case ServiceState.STATE_OUT_OF_SERVICE: - case ServiceState.STATE_EMERGENCY_ONLY: - retVal = mServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE; - break; - default: - retVal = true; + static class WifiSignalController extends + SignalController<WifiSignalController.WifiState, SignalController.IconGroup> { + private final WifiManager mWifiManager; + private final AsyncChannel mWifiChannel; + private final boolean mHasMobileData; + + public WifiSignalController(Context context, boolean hasMobileData, + List<NetworkSignalChangedCallback> signalCallbacks, + List<SignalCluster> signalClusters, NetworkControllerImpl networkController) { + super("WifiSignalController", context, ConnectivityManager.TYPE_WIFI, signalCallbacks, + signalClusters, networkController); + mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + mHasMobileData = hasMobileData; + Handler handler = new WifiHandler(); + mWifiChannel = new AsyncChannel(); + Messenger wifiMessenger = mWifiManager.getWifiServiceMessenger(); + if (wifiMessenger != null) { + mWifiChannel.connect(context, handler, wifiMessenger); } - } else { - retVal = false; + // WiFi only has one state. + mCurrentState.iconGroup = mLastState.iconGroup = new IconGroup( + "Wi-Fi Icons", + WifiIcons.WIFI_SIGNAL_STRENGTH, + WifiIcons.QS_WIFI_SIGNAL_STRENGTH, + AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH, + WifiIcons.WIFI_NO_NETWORK, + WifiIcons.QS_WIFI_NO_NETWORK, + WifiIcons.WIFI_NO_NETWORK, + WifiIcons.QS_WIFI_NO_NETWORK, + AccessibilityContentDescriptions.WIFI_NO_CONNECTION + ); } - if (DEBUG) Log.d(TAG, "hasService: mServiceState=" + mServiceState + " retVal=" + retVal); - return retVal; - } - - private void updateAirplaneMode() { - mAirplaneMode = (Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.AIRPLANE_MODE_ON, 0) == 1); - } - private void refreshLocale() { - mLocale = mContext.getResources().getConfiguration().locale; - } + @Override + public WifiState cleanState() { + return new WifiState(); + } - private final void updateTelephonySignalStrength() { - if (DEBUG) { - Log.d(TAG, "updateTelephonySignalStrength: hasService=" + hasService() - + " ss=" + mSignalStrength); - } - if (!hasService()) { - if (CHATTY) Log.d(TAG, "updateTelephonySignalStrength: !hasService()"); - mPhoneSignalIconId = R.drawable.stat_sys_signal_null; - mQSPhoneSignalIconId = R.drawable.ic_qs_signal_no_signal; - mDataSignalIconId = R.drawable.stat_sys_signal_null; - mContentDescriptionPhoneSignal = mContext.getString( - AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0]); - } else { - if (mSignalStrength == null) { - if (CHATTY) Log.d(TAG, "updateTelephonySignalStrength: mSignalStrength == null"); - mPhoneSignalIconId = R.drawable.stat_sys_signal_null; - mQSPhoneSignalIconId = R.drawable.ic_qs_signal_no_signal; - mDataSignalIconId = R.drawable.stat_sys_signal_null; - mContentDescriptionPhoneSignal = mContext.getString( - AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0]); - } else { - int iconLevel; - int[] iconList; - if (isCdma() && mAlwaysShowCdmaRssi) { - mLastSignalLevel = iconLevel = mSignalStrength.getCdmaLevel(); - if (DEBUG) { - Log.d(TAG, "updateTelephonySignalStrength:" - + " mAlwaysShowCdmaRssi=" + mAlwaysShowCdmaRssi - + " set to cdmaLevel=" + mSignalStrength.getCdmaLevel() - + " instead of level=" + mSignalStrength.getLevel()); - } - } else { - mLastSignalLevel = iconLevel = mSignalStrength.getLevel(); - } + /** + * {@inheritDoc} + */ + @Override + public void notifyListeners() { + // only show wifi in the cluster if connected or if wifi-only + boolean wifiEnabled = mCurrentState.enabled + && (mCurrentState.connected || !mHasMobileData); + String wifiDesc = wifiEnabled ? mCurrentState.ssid : null; + boolean ssidPresent = wifiEnabled && mCurrentState.ssid != null; + String contentDescription = getStringIfExists(getContentDescription()); + int length = mSignalsChangedCallbacks.size(); + for (int i = 0; i < length; i++) { + mSignalsChangedCallbacks.get(i).onWifiSignalChanged(mCurrentState.enabled, + mCurrentState.connected, getQsCurrentIconId(), + ssidPresent && mCurrentState.activityIn, + ssidPresent && mCurrentState.activityOut, contentDescription, wifiDesc); + } - if (isRoaming()) { - iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[mInetCondition]; - } else { - iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[mInetCondition]; - } - mPhoneSignalIconId = iconList[iconLevel]; - mQSPhoneSignalIconId = - TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[mInetCondition][iconLevel]; - mContentDescriptionPhoneSignal = mContext.getString( - AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[iconLevel]); - mDataSignalIconId = TelephonyIcons.DATA_SIGNAL_STRENGTH[mInetCondition][iconLevel]; - if (DEBUG) Log.d(TAG, "updateTelephonySignalStrength: iconLevel=" + iconLevel); + int signalClustersLength = mSignalClusters.size(); + for (int i = 0; i < signalClustersLength; i++) { + mSignalClusters.get(i).setWifiIndicators( + // only show wifi in the cluster if connected or if wifi-only + mCurrentState.enabled && (mCurrentState.connected || !mHasMobileData), + getCurrentIconId(), contentDescription); } } - } - - private int inetConditionForNetwork(int networkType) { - return (mInetCondition == 1 && mConnectedNetworkType == networkType) ? 1 : 0; - } - private final void updateDataNetType() { - int inetCondition; - mDataTypeIconId = mQSDataTypeIconId = 0; - if (mIsWimaxEnabled && mWimaxConnected) { - // wimax is a special 4g network not handled by telephony - inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_WIMAX); - mDataIconList = TelephonyIcons.DATA_4G[inetCondition]; - mDataTypeIconId = R.drawable.stat_sys_data_fully_connected_4g; - mQSDataTypeIconId = TelephonyIcons.QS_DATA_4G[inetCondition]; - mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_4g); - } else { - inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_MOBILE); - final boolean showDataTypeIcon = (inetCondition > 0); - switch (mDataNetType) { - case TelephonyManager.NETWORK_TYPE_UNKNOWN: - if (!mShowAtLeastThreeGees) { - mDataIconList = TelephonyIcons.DATA_G[inetCondition]; - mContentDescriptionDataType = ""; - break; - } else { - // fall through - } - case TelephonyManager.NETWORK_TYPE_EDGE: - if (!mShowAtLeastThreeGees) { - mDataIconList = TelephonyIcons.DATA_E[inetCondition]; - mDataTypeIconId = showDataTypeIcon ? - R.drawable.stat_sys_data_fully_connected_e : 0; - mQSDataTypeIconId = TelephonyIcons.QS_DATA_E[inetCondition]; - mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_edge); - break; - } else { - // fall through - } - case TelephonyManager.NETWORK_TYPE_UMTS: - mDataIconList = TelephonyIcons.DATA_3G[inetCondition]; - mDataTypeIconId = showDataTypeIcon ? - R.drawable.stat_sys_data_fully_connected_3g : 0; - mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[inetCondition]; - mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_3g); - break; - case TelephonyManager.NETWORK_TYPE_HSDPA: - case TelephonyManager.NETWORK_TYPE_HSUPA: - case TelephonyManager.NETWORK_TYPE_HSPA: - case TelephonyManager.NETWORK_TYPE_HSPAP: - if (mHspaDataDistinguishable) { - mDataIconList = TelephonyIcons.DATA_H[inetCondition]; - mDataTypeIconId = showDataTypeIcon ? - R.drawable.stat_sys_data_fully_connected_h : 0; - mQSDataTypeIconId = TelephonyIcons.QS_DATA_H[inetCondition]; - mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_3_5g); + /** + * Extract wifi state directly from broadcasts about changes in wifi state. + */ + public void handleBroadcast(Intent intent) { + String action = intent.getAction(); + if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { + mCurrentState.enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, + WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED; + } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { + final NetworkInfo networkInfo = (NetworkInfo) + intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); + mCurrentState.connected = networkInfo != null && networkInfo.isConnected(); + // If Connected grab the signal strength and ssid. + if (mCurrentState.connected) { + // try getting it out of the intent first + WifiInfo info = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO) != null + ? (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO) + : mWifiManager.getConnectionInfo(); + if (info != null) { + mCurrentState.ssid = huntForSsid(info); } else { - mDataIconList = TelephonyIcons.DATA_3G[inetCondition]; - mDataTypeIconId = showDataTypeIcon ? - R.drawable.stat_sys_data_fully_connected_3g : 0; - mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[inetCondition]; - mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_3g); + mCurrentState.ssid = null; } - break; - case TelephonyManager.NETWORK_TYPE_CDMA: - if (!mShowAtLeastThreeGees) { - // display 1xRTT for IS95A/B - mDataIconList = TelephonyIcons.DATA_1X[inetCondition]; - mDataTypeIconId = showDataTypeIcon ? - R.drawable.stat_sys_data_fully_connected_1x : 0; - mQSDataTypeIconId = TelephonyIcons.QS_DATA_1X[inetCondition]; - mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_cdma); - break; - } else { - // fall through - } - case TelephonyManager.NETWORK_TYPE_1xRTT: - if (!mShowAtLeastThreeGees) { - mDataIconList = TelephonyIcons.DATA_1X[inetCondition]; - mDataTypeIconId = showDataTypeIcon ? - R.drawable.stat_sys_data_fully_connected_1x : 0; - mQSDataTypeIconId = TelephonyIcons.QS_DATA_1X[inetCondition]; - mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_cdma); - break; - } else { - // fall through - } - case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through - case TelephonyManager.NETWORK_TYPE_EVDO_A: - case TelephonyManager.NETWORK_TYPE_EVDO_B: - case TelephonyManager.NETWORK_TYPE_EHRPD: - mDataIconList = TelephonyIcons.DATA_3G[inetCondition]; - mDataTypeIconId = showDataTypeIcon ? - R.drawable.stat_sys_data_fully_connected_3g : 0; - mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[inetCondition]; - mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_3g); - break; - case TelephonyManager.NETWORK_TYPE_LTE: - boolean show4GforLTE = mContext.getResources().getBoolean(R.bool.config_show4GForLTE); - if (show4GforLTE) { - mDataIconList = TelephonyIcons.DATA_4G[inetCondition]; - mDataTypeIconId = showDataTypeIcon ? - R.drawable.stat_sys_data_fully_connected_4g : 0; - mQSDataTypeIconId = TelephonyIcons.QS_DATA_4G[inetCondition]; - mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_4g); - } else { - mDataIconList = TelephonyIcons.DATA_LTE[inetCondition]; - mDataTypeIconId = showDataTypeIcon ? TelephonyIcons.ICON_LTE : 0; - mQSDataTypeIconId = TelephonyIcons.QS_DATA_LTE[inetCondition]; - mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_lte); - } - break; - default: - if (!mShowAtLeastThreeGees) { - mDataIconList = TelephonyIcons.DATA_G[inetCondition]; - mDataTypeIconId = showDataTypeIcon ? - R.drawable.stat_sys_data_fully_connected_g : 0; - mQSDataTypeIconId = TelephonyIcons.QS_DATA_G[inetCondition]; - mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_gprs); - } else { - mDataIconList = TelephonyIcons.DATA_3G[inetCondition]; - mDataTypeIconId = showDataTypeIcon ? - R.drawable.stat_sys_data_fully_connected_3g : 0; - mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[inetCondition]; - mContentDescriptionDataType = mContext.getString( - R.string.accessibility_data_connection_3g); - } - break; + } else if (!mCurrentState.connected) { + mCurrentState.ssid = null; + } + } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) { + mCurrentState.rssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200); + mCurrentState.level = WifiManager.calculateSignalLevel( + mCurrentState.rssi, WifiIcons.WIFI_LEVEL_COUNT); } - } - if (isRoaming()) { - mDataTypeIconId = TelephonyIcons.ROAMING_ICON; - mQSDataTypeIconId = TelephonyIcons.QS_DATA_R[mInetCondition]; + notifyListenersIfNecessary(); } - } - boolean isCdmaEri() { - if (mServiceState != null) { - final int iconIndex = mServiceState.getCdmaEriIconIndex(); - if (iconIndex != EriInfo.ROAMING_INDICATOR_OFF) { - final int iconMode = mServiceState.getCdmaEriIconMode(); - if (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL - || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH) { - return true; + private String huntForSsid(WifiInfo info) { + String ssid = info.getSSID(); + if (ssid != null) { + return ssid; + } + // OK, it's not in the connectionInfo; we have to go hunting for it + List<WifiConfiguration> networks = mWifiManager.getConfiguredNetworks(); + int length = networks.size(); + for (int i = 0; i < length; i++) { + if (networks.get(i).networkId == info.getNetworkId()) { + return networks.get(i).SSID; } } + return null; } - return false; - } - private boolean isRoaming() { - if (isCdma()) { - return isCdmaEri(); - } else { - return mServiceState != null && mServiceState.getRoaming(); + @VisibleForTesting + void setActivity(int wifiActivity) { + mCurrentState.activityIn = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT + || wifiActivity == WifiManager.DATA_ACTIVITY_IN; + mCurrentState.activityOut = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT + || wifiActivity == WifiManager.DATA_ACTIVITY_OUT; + notifyListenersIfNecessary(); } - } - private final void updateDataIcon() { - int iconId; - boolean visible = true; - - if (!isCdma()) { - // GSM case, we have to check also the sim state - if (mSimState == IccCardConstants.State.READY || - mSimState == IccCardConstants.State.UNKNOWN) { - mNoSim = false; - if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) { - switch (mDataActivity) { - case TelephonyManager.DATA_ACTIVITY_IN: - iconId = mDataIconList[1]; - break; - case TelephonyManager.DATA_ACTIVITY_OUT: - iconId = mDataIconList[2]; - break; - case TelephonyManager.DATA_ACTIVITY_INOUT: - iconId = mDataIconList[3]; - break; - default: - iconId = mDataIconList[0]; - break; - } - mDataDirectionIconId = iconId; - } else { - iconId = 0; - visible = false; - } - } else { - iconId = 0; - mNoSim = true; - visible = false; // no SIM? no data - } - } else { - // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT - if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) { - switch (mDataActivity) { - case TelephonyManager.DATA_ACTIVITY_IN: - iconId = mDataIconList[1]; - break; - case TelephonyManager.DATA_ACTIVITY_OUT: - iconId = mDataIconList[2]; + /** + * Handler to receive the data activity on wifi. + */ + class WifiHandler extends Handler { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: + if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { + mWifiChannel.sendMessage(Message.obtain(this, + AsyncChannel.CMD_CHANNEL_FULL_CONNECTION)); + } else { + Log.e(mTag, "Failed to connect to wifi"); + } break; - case TelephonyManager.DATA_ACTIVITY_INOUT: - iconId = mDataIconList[3]; + case WifiManager.DATA_ACTIVITY_NOTIFICATION: + setActivity(msg.arg1); break; - case TelephonyManager.DATA_ACTIVITY_DORMANT: default: - iconId = mDataIconList[0]; + // Ignore break; } - } else { - iconId = 0; - visible = false; } } - mDataDirectionIconId = iconId; - mDataConnected = visible; - } + static class WifiState extends SignalController.State { + String ssid; - void updateNetworkName(boolean showSpn, String spn, boolean showPlmn, String plmn) { - if (false) { - Log.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn + " spn=" + spn - + " showPlmn=" + showPlmn + " plmn=" + plmn); - } - StringBuilder str = new StringBuilder(); - boolean something = false; - if (showPlmn && plmn != null) { - str.append(plmn); - something = true; - } - if (showSpn && spn != null) { - if (something) { - str.append(mNetworkNameSeparator); + @Override + public void copyFrom(State s) { + WifiState state = (WifiState) s; + ssid = state.ssid; + super.copyFrom(s); } - str.append(spn); - something = true; - } - if (something) { - mNetworkName = str.toString(); - } else { - mNetworkName = mNetworkNameDefault; - } - } - // ===== Wifi =================================================================== + @Override + protected void toString(StringBuilder builder) { + builder.append("ssid=").append(ssid).append(','); + super.toString(builder); + } - class WifiHandler extends Handler { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: - if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { - mWifiChannel.sendMessage(Message.obtain(this, - AsyncChannel.CMD_CHANNEL_FULL_CONNECTION)); - } else { - Log.e(TAG, "Failed to connect to wifi"); - } - break; - case WifiManager.DATA_ACTIVITY_NOTIFICATION: - if (msg.arg1 != mWifiActivity) { - mWifiActivity = msg.arg1; - refreshViews(); - } - break; - default: - //Ignore - break; + @Override + public boolean equals(Object o) { + return super.equals(o) + && Objects.equals(((WifiState) o).ssid, ssid); } } } - private void updateWifiState(Intent intent) { - final String action = intent.getAction(); - if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { - mWifiEnabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, - WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED; - - } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { - final NetworkInfo networkInfo = (NetworkInfo) - intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); - boolean wasConnected = mWifiConnected; - mWifiConnected = networkInfo != null && networkInfo.isConnected(); - // If Connected grab the signal strength and ssid - if (mWifiConnected) { - // try getting it out of the intent first - WifiInfo info = (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO); - if (info == null) { - info = mWifiManager.getConnectionInfo(); + static class MobileSignalController extends SignalController<MobileSignalController.MobileState, + MobileSignalController.MobileIconGroup> { + private final Config mConfig; + private final TelephonyManager mPhone; + private final String mNetworkNameDefault; + private final String mNetworkNameSeparator; + + // @VisibleForDemoMode + Map<Integer, MobileIconGroup> mNetworkToIconLookup; + + // Since some pieces of the phone state are interdependent we store it locally, + // this could potentially become part of MobileState for simplification/complication + // of code. + private IccCardConstants.State mSimState = IccCardConstants.State.READY; + private int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN; + private int mDataState = TelephonyManager.DATA_DISCONNECTED; + private ServiceState mServiceState; + private SignalStrength mSignalStrength; + private MobileIconGroup mDefaultIcons; + + // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't + // need listener lists anymore. + public MobileSignalController(Context context, Config config, boolean hasMobileData, + TelephonyManager phone, List<NetworkSignalChangedCallback> signalCallbacks, + List<SignalCluster> signalClusters, NetworkControllerImpl networkController) { + super("MobileSignalController", context, ConnectivityManager.TYPE_MOBILE, + signalCallbacks, signalClusters, networkController); + mConfig = config; + mPhone = phone; + mNetworkNameSeparator = getStringIfExists(R.string.status_bar_network_name_separator); + mNetworkNameDefault = getStringIfExists( + com.android.internal.R.string.lockscreen_carrier_default); + + mapIconSets(); + + mLastState.networkName = mCurrentState.networkName = mNetworkNameDefault; + mLastState.enabled = mCurrentState.enabled = hasMobileData; + mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons; + } + + /** + * Get (the mobile parts of) the carrier string. + * + * @param currentLabel can be used for concatenation, currently just empty + * @param connected whether the device has connection to the internet at all + * @param isMobileLabel whether to always return the network or just when data is connected + */ + public String getLabel(String currentLabel, boolean connected, boolean isMobileLabel) { + if (!mCurrentState.enabled) { + return ""; + } else { + String mobileLabel = ""; + // We want to show the carrier name if in service and either: + // - We are connected to mobile data, or + // - We are not connected to mobile data, as long as the *reason* packets are not + // being routed over that link is that we have better connectivity via wifi. + // If data is disconnected for some other reason but wifi (or ethernet/bluetooth) + // is connected, we show nothing. + // Otherwise (nothing connected) we show "No internet connection". + if (mCurrentState.dataConnected) { + mobileLabel = mCurrentState.networkName; + } else if (connected || mCurrentState.isEmergency) { + if (mCurrentState.connected || mCurrentState.isEmergency) { + // The isEmergencyOnly test covers the case of a phone with no SIM + mobileLabel = mCurrentState.networkName; + } + } else { + mobileLabel = mContext + .getString(R.string.status_bar_settings_signal_meter_disconnected); } - if (info != null) { - mWifiSsid = huntForSsid(info); + + // Now for things that should only be shown when actually using mobile data. + if (isMobileLabel) { + return mobileLabel; } else { - mWifiSsid = null; + return mCurrentState.dataConnected ? mobileLabel : currentLabel; } - } else if (!mWifiConnected) { - mWifiSsid = null; } - } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) { - mWifiRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200); - mWifiLevel = WifiManager.calculateSignalLevel( - mWifiRssi, WifiIcons.WIFI_LEVEL_COUNT); } - updateWifiIcons(); - } + public int getDataContentDescription() { + return getIcons().mDataContentDescription; + } - private void updateWifiIcons() { - int inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_WIFI); - if (mWifiConnected) { - mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[inetCondition][mWifiLevel]; - mQSWifiIconId = WifiIcons.QS_WIFI_SIGNAL_STRENGTH[inetCondition][mWifiLevel]; - mContentDescriptionWifi = mContext.getString( - AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH[mWifiLevel]); - } else { - if (mDataAndWifiStacked) { - mWifiIconId = 0; - mQSWifiIconId = 0; - } else { - mWifiIconId = mWifiEnabled ? R.drawable.stat_sys_wifi_signal_null : 0; - mQSWifiIconId = mWifiEnabled ? R.drawable.ic_qs_wifi_no_network : 0; - } - mContentDescriptionWifi = mContext.getString(R.string.accessibility_no_wifi); + public void setAirplaneMode(boolean airplaneMode) { + mCurrentState.airplaneMode = airplaneMode; + notifyListenersIfNecessary(); } - } - private String huntForSsid(WifiInfo info) { - String ssid = info.getSSID(); - if (ssid != null) { - return ssid; + public void setInetCondition(int inetCondition, int inetConditionForNetwork) { + // For mobile data, use general inet condition for phone signal indexing, + // and network specific for data indexing (I think this might be a bug, but + // keeping for now). + // TODO: Update with explanation of why. + mCurrentState.inetForNetwork = inetConditionForNetwork; + setInetCondition(inetCondition); } - // OK, it's not in the connectionInfo; we have to go hunting for it - List<WifiConfiguration> networks = mWifiManager.getConfiguredNetworks(); - for (WifiConfiguration net : networks) { - if (net.networkId == info.getNetworkId()) { - return net.SSID; - } + + /** + * Start listening for phone state changes. + */ + public void registerListener() { + mPhone.listen(mPhoneStateListener, + PhoneStateListener.LISTEN_SERVICE_STATE + | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS + | PhoneStateListener.LISTEN_CALL_STATE + | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE + | PhoneStateListener.LISTEN_DATA_ACTIVITY); } - return null; - } + /** + * Stop listening for phone state changes. + */ + public void unregisterListener() { + mPhone.listen(mPhoneStateListener, 0); + } - // ===== Wimax =================================================================== - private final void updateWimaxState(Intent intent) { - final String action = intent.getAction(); - boolean wasConnected = mWimaxConnected; - if (action.equals(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION)) { - int wimaxStatus = intent.getIntExtra(WimaxManagerConstants.EXTRA_4G_STATE, - WimaxManagerConstants.NET_4G_STATE_UNKNOWN); - mIsWimaxEnabled = (wimaxStatus == - WimaxManagerConstants.NET_4G_STATE_ENABLED); - } else if (action.equals(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION)) { - mWimaxSignal = intent.getIntExtra(WimaxManagerConstants.EXTRA_NEW_SIGNAL_LEVEL, 0); - } else if (action.equals(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION)) { - mWimaxState = intent.getIntExtra(WimaxManagerConstants.EXTRA_WIMAX_STATE, - WimaxManagerConstants.NET_4G_STATE_UNKNOWN); - mWimaxExtraState = intent.getIntExtra( - WimaxManagerConstants.EXTRA_WIMAX_STATE_DETAIL, - WimaxManagerConstants.NET_4G_STATE_UNKNOWN); - mWimaxConnected = (mWimaxState == - WimaxManagerConstants.WIMAX_STATE_CONNECTED); - mWimaxIdle = (mWimaxExtraState == WimaxManagerConstants.WIMAX_IDLE); - } - updateDataNetType(); - updateWimaxIcons(); - } + /** + * Produce a mapping of data network types to icon groups for simple and quick use in + * updateTelephony. + * + * TODO: See if config can change with locale, this may need to be regenerated on Locale + * change. + */ + private void mapIconSets() { + mNetworkToIconLookup = new HashMap<Integer, MobileIconGroup>(); + + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyIcons.THREE_G); + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyIcons.THREE_G); + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_B, TelephonyIcons.THREE_G); + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyIcons.THREE_G); + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UMTS, TelephonyIcons.THREE_G); - private void updateWimaxIcons() { - if (mIsWimaxEnabled) { - if (mWimaxConnected) { - int inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_WIMAX); - if (mWimaxIdle) - mWimaxIconId = WimaxIcons.WIMAX_IDLE; - else - mWimaxIconId = WimaxIcons.WIMAX_SIGNAL_STRENGTH[inetCondition][mWimaxSignal]; - mContentDescriptionWimax = mContext.getString( - AccessibilityContentDescriptions.WIMAX_CONNECTION_STRENGTH[mWimaxSignal]); + if (!mConfig.showAtLeastThreeGees) { + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN, + TelephonyIcons.UNKNOWN); + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE, TelephonyIcons.E); + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA, TelephonyIcons.ONE_X); + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyIcons.ONE_X); + + mDefaultIcons = TelephonyIcons.G; } else { - mWimaxIconId = WimaxIcons.WIMAX_DISCONNECTED; - mContentDescriptionWimax = mContext.getString(R.string.accessibility_no_wimax); + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN, + TelephonyIcons.THREE_G); + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE, + TelephonyIcons.THREE_G); + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA, + TelephonyIcons.THREE_G); + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT, + TelephonyIcons.THREE_G); + mDefaultIcons = TelephonyIcons.THREE_G; } - } else { - mWimaxIconId = 0; - } - } - // ===== Full or limited Internet connectivity ================================== + MobileIconGroup hGroup = TelephonyIcons.THREE_G; + if (mConfig.hspaDataDistinguishable) { + hGroup = TelephonyIcons.H; + } + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSDPA, hGroup); + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSUPA, hGroup); + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPA, hGroup); + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPAP, hGroup); - private void updateConnectivity(Intent intent) { - if (CHATTY) { - Log.d(TAG, "updateConnectivity: intent=" + intent); + if (mConfig.show4gForLte) { + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.FOUR_G); + } else { + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.LTE); + } } - final NetworkInfo info = mConnectivityManager.getActiveNetworkInfo(); - - // Are we connected at all, by any interface? - mConnected = info != null && info.isConnected(); - if (mConnected) { - mConnectedNetworkType = info.getType(); - mConnectedNetworkTypeName = info.getTypeName(); - } else { - mConnectedNetworkType = ConnectivityManager.TYPE_NONE; - mConnectedNetworkTypeName = null; + /** + * {@inheritDoc} + */ + @Override + public void notifyListeners() { + MobileIconGroup icons = getIcons(); + + String contentDescription = getStringIfExists(getContentDescription()); + String dataContentDescription = getStringIfExists(icons.mDataContentDescription); + int qsTypeIcon = icons.mQsDataType[mCurrentState.inetForNetwork]; + int length = mSignalsChangedCallbacks.size(); + for (int i = 0; i < length; i++) { + mSignalsChangedCallbacks.get(i).onMobileDataSignalChanged(mCurrentState.enabled + && !mCurrentState.isEmergency && !mCurrentState.airplaneMode, + getQsCurrentIconId(), contentDescription, + qsTypeIcon, + mCurrentState.dataConnected && mCurrentState.activityIn, + mCurrentState.dataConnected && mCurrentState.activityOut, + dataContentDescription, + mCurrentState.isEmergency ? null : mCurrentState.networkName, + mCurrentState.noSim, + // Only wide if actually showing something. + icons.mIsWide && qsTypeIcon != 0); + } + boolean showDataIcon = mCurrentState.inetForNetwork != 0 + || mCurrentState.iconGroup == TelephonyIcons.ROAMING; + int typeIcon = showDataIcon ? icons.mDataType : 0; + int signalClustersLength = mSignalClusters.size(); + for (int i = 0; i < signalClustersLength; i++) { + mSignalClusters.get(i).setMobileDataIndicators( + mCurrentState.enabled && !mCurrentState.airplaneMode, + getCurrentIconId(), + typeIcon, + contentDescription, + dataContentDescription, + // Only wide if actually showing something. + icons.mIsWide && typeIcon != 0); + } } - int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0); - - if (CHATTY) { - Log.d(TAG, "updateConnectivity: networkInfo=" + info); - Log.d(TAG, "updateConnectivity: connectionStatus=" + connectionStatus); + @Override + public MobileState cleanState() { + return new MobileState(); + } + + private boolean hasService() { + if (mServiceState != null) { + // Consider the device to be in service if either voice or data + // service is available. Some SIM cards are marketed as data-only + // and do not support voice service, and on these SIM cards, we + // want to show signal bars for data service as well as the "no + // service" or "emergency calls only" text that indicates that voice + // is not available. + switch (mServiceState.getVoiceRegState()) { + case ServiceState.STATE_POWER_OFF: + return false; + case ServiceState.STATE_OUT_OF_SERVICE: + case ServiceState.STATE_EMERGENCY_ONLY: + return mServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE; + default: + return true; + } + } else { + return false; + } } - mInetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0); - - if (info != null && info.getType() == ConnectivityManager.TYPE_BLUETOOTH) { - mBluetoothTethered = info.isConnected(); - } else { - mBluetoothTethered = false; + private boolean isCdma() { + return (mSignalStrength != null) && !mSignalStrength.isGsm(); } - // We want to update all the icons, all at once, for any condition change - updateDataNetType(); - updateWimaxIcons(); - updateDataIcon(); - updateTelephonySignalStrength(); - updateWifiIcons(); - } - - - // ===== Update the views ======================================================= + public boolean isEmergencyOnly() { + return (mServiceState != null && mServiceState.isEmergencyOnly()); + } - void refreshViews() { - Context context = mContext; + private boolean isRoaming() { + if (isCdma()) { + final int iconMode = mServiceState.getCdmaEriIconMode(); + return mServiceState.getCdmaEriIconIndex() != EriInfo.ROAMING_INDICATOR_OFF + && (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL + || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH); + } else { + return mServiceState != null && mServiceState.getRoaming(); + } + } - int combinedSignalIconId = 0; - String combinedLabel = ""; - String wifiLabel = ""; - String mobileLabel = ""; - int N; - final boolean emergencyOnly = isEmergencyOnly(); + public void handleBroadcast(Intent intent) { + String action = intent.getAction(); + if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) { + String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); + final String lockedReason = + intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON); + updateSimState(stateExtra, lockedReason); + updateTelephony(); + } else if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) { + updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false), + intent.getStringExtra(TelephonyIntents.EXTRA_SPN), + intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false), + intent.getStringExtra(TelephonyIntents.EXTRA_PLMN)); + notifyListenersIfNecessary(); + } + } - if (!mHasMobileDataFeature) { - mDataSignalIconId = mPhoneSignalIconId = 0; - mQSPhoneSignalIconId = 0; - mobileLabel = ""; - } else { - // We want to show the carrier name if in service and either: - // - We are connected to mobile data, or - // - We are not connected to mobile data, as long as the *reason* packets are not - // being routed over that link is that we have better connectivity via wifi. - // If data is disconnected for some other reason but wifi (or ethernet/bluetooth) - // is connected, we show nothing. - // Otherwise (nothing connected) we show "No internet connection". - - if (mDataConnected) { - mobileLabel = mNetworkName; - } else if (mConnected || emergencyOnly) { - if (hasService() || emergencyOnly) { - // The isEmergencyOnly test covers the case of a phone with no SIM - mobileLabel = mNetworkName; + /** + * Determines the current sim state, based on a TelephonyIntents.ACTION_SIM_STATE_CHANGED + * broadcast. + */ + private final void updateSimState(String stateExtra, String lockedReason) { + if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) { + mSimState = IccCardConstants.State.ABSENT; + } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) { + mSimState = IccCardConstants.State.READY; + } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) { + if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) { + mSimState = IccCardConstants.State.PIN_REQUIRED; + } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) { + mSimState = IccCardConstants.State.PUK_REQUIRED; } else { - // Tablets, basically - mobileLabel = ""; + mSimState = IccCardConstants.State.NETWORK_LOCKED; } } else { - mobileLabel - = context.getString(R.string.status_bar_settings_signal_meter_disconnected); + mSimState = IccCardConstants.State.UNKNOWN; } + if (DEBUG) Log.d(TAG, "updateSimState: mSimState=" + mSimState); + } - // Now for things that should only be shown when actually using mobile data. - if (mDataConnected) { - combinedSignalIconId = mDataSignalIconId; - - combinedLabel = mobileLabel; - combinedSignalIconId = mDataSignalIconId; // set by updateDataIcon() - mContentDescriptionCombinedSignal = mContentDescriptionDataType; + /** + * Updates the network's name based on incoming spn and plmn. + */ + void updateNetworkName(boolean showSpn, String spn, boolean showPlmn, String plmn) { + if (CHATTY) { + Log.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn + " spn=" + spn + + " showPlmn=" + showPlmn + " plmn=" + plmn); + } + StringBuilder str = new StringBuilder(); + if (showPlmn && plmn != null) { + str.append(plmn); + } + if (showSpn && spn != null) { + if (str.length() != 0) { + str.append(mNetworkNameSeparator); + } + str.append(spn); + } + if (str.length() != 0) { + mCurrentState.networkName = str.toString(); + } else { + mCurrentState.networkName = mNetworkNameDefault; } } - if (mWifiConnected) { - if (mWifiSsid == null) { - wifiLabel = context.getString(R.string.status_bar_settings_signal_meter_wifi_nossid); + /** + * Updates the current state based on mServiceState, mSignalStrength, mDataNetType, + * mDataState, and mSimState. It should be called any time one of these is updated. + * This will call listeners if necessary. + */ + private final void updateTelephony() { + if (DEBUG) { + Log.d(TAG, "updateTelephonySignalStrength: hasService=" + hasService() + + " ss=" + mSignalStrength); + } + mCurrentState.connected = hasService() && mSignalStrength != null; + if (mCurrentState.connected) { + if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) { + mCurrentState.level = mSignalStrength.getCdmaLevel(); + } else { + mCurrentState.level = mSignalStrength.getLevel(); + } + } + if (mNetworkToIconLookup.containsKey(mDataNetType)) { + mCurrentState.iconGroup = mNetworkToIconLookup.get(mDataNetType); } else { - wifiLabel = mWifiSsid; - if (DEBUG) { - wifiLabel += "xxxxXXXXxxxxXXXX"; + mCurrentState.iconGroup = mDefaultIcons; + } + mCurrentState.dataConnected = mCurrentState.connected + && mDataState == TelephonyManager.DATA_CONNECTED; + if (!isCdma()) { + if (mSimState == IccCardConstants.State.READY || + mSimState == IccCardConstants.State.UNKNOWN) { + mCurrentState.noSim = false; + } else { + mCurrentState.noSim = true; + // No sim, no data. + mCurrentState.dataConnected = false; } } - combinedLabel = wifiLabel; - combinedSignalIconId = mWifiIconId; // set by updateWifiIcons() - mContentDescriptionCombinedSignal = mContentDescriptionWifi; - } else { - if (mHasMobileDataFeature) { - wifiLabel = ""; - } else { - wifiLabel = context.getString(R.string.status_bar_settings_signal_meter_disconnected); + if (isRoaming()) { + mCurrentState.iconGroup = TelephonyIcons.ROAMING; + } + if (isEmergencyOnly() != mCurrentState.isEmergency) { + mCurrentState.isEmergency = isEmergencyOnly(); + mNetworkController.recalculateEmergency(); } + notifyListenersIfNecessary(); } - if (mBluetoothTethered) { - combinedLabel = mContext.getString(R.string.bluetooth_tethered); - combinedSignalIconId = mBluetoothTetherIconId; - mContentDescriptionCombinedSignal = mContext.getString( - R.string.accessibility_bluetooth_tether); + @VisibleForTesting + void setActivity(int activity) { + mCurrentState.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT + || activity == TelephonyManager.DATA_ACTIVITY_IN; + mCurrentState.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT + || activity == TelephonyManager.DATA_ACTIVITY_OUT; + notifyListenersIfNecessary(); } - final boolean ethernetConnected = (mConnectedNetworkType == ConnectivityManager.TYPE_ETHERNET); - if (ethernetConnected) { - combinedLabel = context.getString(R.string.ethernet_label); + @Override + public void dump(PrintWriter pw) { + super.dump(pw); + pw.println(" mServiceState=" + mServiceState + ","); + pw.println(" mSignalStrength=" + mSignalStrength + ","); + pw.println(" mDataState=" + mDataState + ","); + pw.println(" mDataNetType=" + mDataNetType + ","); } - if (mAirplaneMode && - (mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly()))) { - // Only display the flight-mode icon if not in "emergency calls only" mode. - - // look again; your radios are now airplanes - mContentDescriptionPhoneSignal = mContext.getString( - R.string.accessibility_airplane_mode); - mAirplaneIconId = TelephonyIcons.FLIGHT_MODE_ICON; - mPhoneSignalIconId = mDataSignalIconId = mDataTypeIconId = mQSDataTypeIconId = 0; - mQSPhoneSignalIconId = 0; - - // combined values from connected wifi take precedence over airplane mode - if (mWifiConnected) { - // Suppress "No internet connection." from mobile if wifi connected. - mobileLabel = ""; - } else { - if (mHasMobileDataFeature) { - // let the mobile icon show "No internet connection." - wifiLabel = ""; - } else { - wifiLabel = context.getString(R.string.status_bar_settings_signal_meter_disconnected); - combinedLabel = wifiLabel; + PhoneStateListener mPhoneStateListener = new PhoneStateListener() { + @Override + public void onSignalStrengthsChanged(SignalStrength signalStrength) { + if (DEBUG) { + Log.d(TAG, "onSignalStrengthsChanged signalStrength=" + signalStrength + + ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel()))); } - mContentDescriptionCombinedSignal = mContentDescriptionPhoneSignal; - combinedSignalIconId = mDataSignalIconId; + mSignalStrength = signalStrength; + updateTelephony(); } - } - else if (!mDataConnected && !mWifiConnected && !mBluetoothTethered && !mWimaxConnected && !ethernetConnected) { - // pretty much totally disconnected - combinedLabel = context.getString(R.string.status_bar_settings_signal_meter_disconnected); - // On devices without mobile radios, we want to show the wifi icon - combinedSignalIconId = - mHasMobileDataFeature ? mDataSignalIconId : mWifiIconId; - mContentDescriptionCombinedSignal = mHasMobileDataFeature - ? mContentDescriptionDataType : mContentDescriptionWifi; + @Override + public void onServiceStateChanged(ServiceState state) { + if (DEBUG) { + Log.d(TAG, "onServiceStateChanged voiceState=" + state.getVoiceRegState() + + " dataState=" + state.getDataRegState()); + } + mServiceState = state; + updateTelephony(); + } - int inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_MOBILE); + @Override + public void onDataConnectionStateChanged(int state, int networkType) { + if (DEBUG) { + Log.d(TAG, "onDataConnectionStateChanged: state=" + state + + " type=" + networkType); + } + mDataState = state; + mDataNetType = networkType; + updateTelephony(); + } - mDataTypeIconId = 0; - mQSDataTypeIconId = 0; - if (isRoaming()) { - mDataTypeIconId = TelephonyIcons.ROAMING_ICON; - mQSDataTypeIconId = TelephonyIcons.QS_DATA_R[mInetCondition]; + @Override + public void onDataActivity(int direction) { + if (DEBUG) { + Log.d(TAG, "onDataActivity: direction=" + direction); + } + setActivity(direction); + } + }; + + static class MobileIconGroup extends SignalController.IconGroup { + final int mDataContentDescription; // mContentDescriptionDataType + final int mDataType; + final boolean mIsWide; + final int[] mQsDataType; + + public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc, + int sbNullState, int qsNullState, int sbDiscState, int qsDiscState, + int discContentDesc, int dataContentDesc, int dataType, boolean isWide, + int[] qsDataType) { + super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState, + qsDiscState, discContentDesc); + mDataContentDescription = dataContentDesc; + mDataType = dataType; + mIsWide = isWide; + mQsDataType = qsDataType; } } - if (mDemoMode) { - mQSWifiIconId = mDemoWifiLevel < 0 ? R.drawable.ic_qs_wifi_no_network - : WifiIcons.QS_WIFI_SIGNAL_STRENGTH[mDemoInetCondition][mDemoWifiLevel]; - mQSPhoneSignalIconId = mDemoMobileLevel < 0 ? R.drawable.ic_qs_signal_no_signal : - TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[mDemoInetCondition][mDemoMobileLevel]; - mQSDataTypeIconId = mDemoQSDataTypeIconId; - } - - if (DEBUG) { - Log.d(TAG, "refreshViews connected={" - + (mWifiConnected?" wifi":"") - + (mDataConnected?" data":"") - + " } level=" - + ((mSignalStrength == null)?"??":Integer.toString(mSignalStrength.getLevel())) - + " combinedSignalIconId=0x" - + Integer.toHexString(combinedSignalIconId) - + "/" + getResourceName(combinedSignalIconId) - + " mobileLabel=" + mobileLabel - + " wifiLabel=" + wifiLabel - + " emergencyOnly=" + emergencyOnly - + " combinedLabel=" + combinedLabel - + " mAirplaneMode=" + mAirplaneMode - + " mDataActivity=" + mDataActivity - + " mPhoneSignalIconId=0x" + Integer.toHexString(mPhoneSignalIconId) - + " mQSPhoneSignalIconId=0x" + Integer.toHexString(mQSPhoneSignalIconId) - + " mDataDirectionIconId=0x" + Integer.toHexString(mDataDirectionIconId) - + " mDataSignalIconId=0x" + Integer.toHexString(mDataSignalIconId) - + " mDataTypeIconId=0x" + Integer.toHexString(mDataTypeIconId) - + " mQSDataTypeIconId=0x" + Integer.toHexString(mQSDataTypeIconId) - + " mWifiIconId=0x" + Integer.toHexString(mWifiIconId) - + " mQSWifiIconId=0x" + Integer.toHexString(mQSWifiIconId) - + " mBluetoothTetherIconId=0x" + Integer.toHexString(mBluetoothTetherIconId)); - } + static class MobileState extends SignalController.State { + String networkName; + boolean noSim; + boolean dataConnected; + boolean isEmergency; + boolean airplaneMode; + int inetForNetwork; - // update QS - for (NetworkSignalChangedCallback cb : mSignalsChangedCallbacks) { - notifySignalsChangedCallbacks(cb); - } - - if (mLastPhoneSignalIconId != mPhoneSignalIconId - || mLastWifiIconId != mWifiIconId - || mLastInetCondition != mInetCondition - || mLastWimaxIconId != mWimaxIconId - || mLastDataTypeIconId != mDataTypeIconId - || mLastAirplaneMode != mAirplaneMode - || mLastLocale != mLocale - || mLastConnectedNetworkType != mConnectedNetworkType) - { - // NB: the mLast*s will be updated later - for (SignalCluster cluster : mSignalClusters) { - refreshSignalCluster(cluster); + @Override + public void copyFrom(State s) { + MobileState state = (MobileState) s; + noSim = state.noSim; + networkName = state.networkName; + dataConnected = state.dataConnected; + inetForNetwork = state.inetForNetwork; + isEmergency = state.isEmergency; + airplaneMode = state.airplaneMode; + super.copyFrom(s); } - } - if (mLastAirplaneMode != mAirplaneMode) { - mLastAirplaneMode = mAirplaneMode; - } + @Override + protected void toString(StringBuilder builder) { + builder.append("noSim=").append(noSim).append(','); + builder.append("networkName=").append(networkName).append(','); + builder.append("dataConnected=").append(dataConnected).append(','); + builder.append("inetForNetwork=").append(inetForNetwork).append(','); + builder.append("isEmergency=").append(isEmergency).append(','); + builder.append("airplaneMode=").append(airplaneMode).append(','); + super.toString(builder); + } - if (mLastLocale != mLocale) { - mLastLocale = mLocale; + @Override + public boolean equals(Object o) { + return super.equals(o) + && Objects.equals(((MobileState) o).networkName, networkName) + && ((MobileState) o).noSim == noSim + && ((MobileState) o).dataConnected == dataConnected + && ((MobileState) o).isEmergency == isEmergency + && ((MobileState) o).airplaneMode == airplaneMode + && ((MobileState) o).inetForNetwork == inetForNetwork; + } } + } - // the phone icon on phones - if (mLastPhoneSignalIconId != mPhoneSignalIconId) { - mLastPhoneSignalIconId = mPhoneSignalIconId; + /** + * Common base class for handling signal for both wifi and mobile data. + */ + static abstract class SignalController<T extends SignalController.State, + I extends SignalController.IconGroup> { + protected final String mTag; + protected final T mCurrentState; + protected final T mLastState; + protected final int mNetworkType; + protected final Context mContext; + // The owner of the SignalController (i.e. NetworkController will maintain the following + // lists and call notifyListeners whenever the list has changed to ensure everyone + // is aware of current state. + protected final List<NetworkSignalChangedCallback> mSignalsChangedCallbacks; + protected final List<SignalCluster> mSignalClusters; + protected final NetworkControllerImpl mNetworkController; + + // Save the previous HISTORY_SIZE states for logging. + private final State[] mHistory; + // Where to copy the next state into. + private int mHistoryIndex; + + public SignalController(String tag, Context context, int type, + List<NetworkSignalChangedCallback> signalCallbacks, + List<SignalCluster> signalClusters, NetworkControllerImpl networkController) { + mTag = TAG + "::" + tag; + mNetworkController = networkController; + mNetworkType = type; + mContext = context; + mSignalsChangedCallbacks = signalCallbacks; + mSignalClusters = signalClusters; + mCurrentState = cleanState(); + mLastState = cleanState(); + if (RECORD_HISTORY) { + mHistory = new State[HISTORY_SIZE]; + for (int i = 0; i < HISTORY_SIZE; i++) { + mHistory[i] = cleanState(); + } + } } - // the data icon on phones - if (mLastDataDirectionIconId != mDataDirectionIconId) { - mLastDataDirectionIconId = mDataDirectionIconId; + public T getState() { + return mCurrentState; } - // the wifi icon on phones - if (mLastWifiIconId != mWifiIconId) { - mLastWifiIconId = mWifiIconId; + public int getNetworkType() { + return mNetworkType; } - if (mLastInetCondition != mInetCondition) { - mLastInetCondition = mInetCondition; + public void setInetCondition(int inetCondition) { + mCurrentState.inetCondition = inetCondition; + notifyListenersIfNecessary(); } - if (mLastConnectedNetworkType != mConnectedNetworkType) { - mLastConnectedNetworkType = mConnectedNetworkType; + // @VisibleForDemoMode + /** + * Used at the end of demo mode to clear out any ugly state that it has created. + * Since we haven't had any callbacks, then isDirty will not have been triggered, + * so we can just take the last good state directly from there. + */ + void resetLastState() { + mCurrentState.copyFrom(mLastState); } - // the wimax icon on phones - if (mLastWimaxIconId != mWimaxIconId) { - mLastWimaxIconId = mWimaxIconId; - } - // the combined data signal icon - if (mLastCombinedSignalIconId != combinedSignalIconId) { - mLastCombinedSignalIconId = combinedSignalIconId; + /** + * Determines if the state of this signal controller has changed and + * needs to trigger callbacks related to it. + */ + public boolean isDirty() { + if (!mLastState.equals(mCurrentState)) { + if (DEBUG) { + Log.d(mTag, "Change in state from: " + mLastState + "\n" + + "\tto: " + mCurrentState); + } + return true; + } + return false; } - // the data network type overlay - if (mLastDataTypeIconId != mDataTypeIconId) { - mLastDataTypeIconId = mDataTypeIconId; + public void saveLastState() { + if (RECORD_HISTORY) { + recordLast(); + } + // Updates the current time. + mCurrentState.time = System.currentTimeMillis(); + mLastState.copyFrom(mCurrentState); + } + + /** + * Gets the signal icon for QS based on current state of connected, enabled, and level. + */ + public int getQsCurrentIconId() { + if (mCurrentState.connected) { + return getIcons().mQsIcons[mCurrentState.inetCondition][mCurrentState.level]; + } else if (mCurrentState.enabled) { + return getIcons().mQsDiscState; + } else { + return getIcons().mQsNullState; + } } - // the combinedLabel in the notification panel - if (!mLastCombinedLabel.equals(combinedLabel)) { - mLastCombinedLabel = combinedLabel; - N = mCombinedLabelViews.size(); - for (int i=0; i<N; i++) { - TextView v = mCombinedLabelViews.get(i); - v.setText(combinedLabel); + /** + * Gets the signal icon for SB based on current state of connected, enabled, and level. + */ + public int getCurrentIconId() { + if (mCurrentState.connected) { + return getIcons().mSbIcons[mCurrentState.inetCondition][mCurrentState.level]; + } else if (mCurrentState.enabled) { + return getIcons().mSbDiscState; + } else { + return getIcons().mSbNullState; } } - // wifi label - N = mWifiLabelViews.size(); - for (int i=0; i<N; i++) { - TextView v = mWifiLabelViews.get(i); - v.setText(wifiLabel); - if ("".equals(wifiLabel)) { - v.setVisibility(View.GONE); + /** + * Gets the content description for the signal based on current state of connected and + * level. + */ + public int getContentDescription() { + if (mCurrentState.connected) { + return getIcons().mContentDesc[mCurrentState.level]; } else { - v.setVisibility(View.VISIBLE); + return getIcons().mDiscContentDesc; } } - // mobile label - N = mMobileLabelViews.size(); - for (int i=0; i<N; i++) { - TextView v = mMobileLabelViews.get(i); - v.setText(mobileLabel); - if ("".equals(mobileLabel)) { - v.setVisibility(View.GONE); - } else { - v.setVisibility(View.VISIBLE); + protected void notifyListenersIfNecessary() { + if (isDirty()) { + saveLastState(); + notifyListeners(); + mNetworkController.refreshCarrierLabel(); } } - // e-call label - N = mEmergencyViews.size(); - for (int i=0; i<N; i++) { - StatusBarHeaderView v = mEmergencyViews.get(i); - v.setShowEmergencyCallsOnly(emergencyOnly); + /** + * Returns the resource if resId is not 0, and an empty string otherwise. + */ + protected String getStringIfExists(int resId) { + return resId != 0 ? mContext.getString(resId) : ""; } - } - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("NetworkController state:"); - pw.println(String.format(" %s network type %d (%s)", - mConnected?"CONNECTED":"DISCONNECTED", - mConnectedNetworkType, mConnectedNetworkTypeName)); - pw.println(" - telephony ------"); - pw.print(" hasVoiceCallingFeature()="); - pw.println(hasVoiceCallingFeature()); - pw.print(" hasService()="); - pw.println(hasService()); - pw.print(" mHspaDataDistinguishable="); - pw.println(mHspaDataDistinguishable); - pw.print(" mDataConnected="); - pw.println(mDataConnected); - pw.print(" mSimState="); - pw.println(mSimState); - pw.print(" mPhoneState="); - pw.println(mPhoneState); - pw.print(" mDataState="); - pw.println(mDataState); - pw.print(" mDataActivity="); - pw.println(mDataActivity); - pw.print(" mDataNetType="); - pw.print(mDataNetType); - pw.print("/"); - pw.println(TelephonyManager.getNetworkTypeName(mDataNetType)); - pw.print(" mServiceState="); - pw.println(mServiceState); - pw.print(" mSignalStrength="); - pw.println(mSignalStrength); - pw.print(" mLastSignalLevel="); - pw.println(mLastSignalLevel); - pw.print(" mNetworkName="); - pw.println(mNetworkName); - pw.print(" mNetworkNameDefault="); - pw.println(mNetworkNameDefault); - pw.print(" mNetworkNameSeparator="); - pw.println(mNetworkNameSeparator.replace("\n","\\n")); - pw.print(" mPhoneSignalIconId=0x"); - pw.print(Integer.toHexString(mPhoneSignalIconId)); - pw.print("/"); - pw.print(" mQSPhoneSignalIconId=0x"); - pw.print(Integer.toHexString(mQSPhoneSignalIconId)); - pw.print("/"); - pw.println(getResourceName(mPhoneSignalIconId)); - pw.print(" mDataDirectionIconId="); - pw.print(Integer.toHexString(mDataDirectionIconId)); - pw.print("/"); - pw.println(getResourceName(mDataDirectionIconId)); - pw.print(" mDataSignalIconId="); - pw.print(Integer.toHexString(mDataSignalIconId)); - pw.print("/"); - pw.println(getResourceName(mDataSignalIconId)); - pw.print(" mDataTypeIconId="); - pw.print(Integer.toHexString(mDataTypeIconId)); - pw.print("/"); - pw.println(getResourceName(mDataTypeIconId)); - pw.print(" mQSDataTypeIconId="); - pw.print(Integer.toHexString(mQSDataTypeIconId)); - pw.print("/"); - pw.println(getResourceName(mQSDataTypeIconId)); - - pw.println(" - wifi ------"); - pw.print(" mWifiEnabled="); - pw.println(mWifiEnabled); - pw.print(" mWifiConnected="); - pw.println(mWifiConnected); - pw.print(" mWifiRssi="); - pw.println(mWifiRssi); - pw.print(" mWifiLevel="); - pw.println(mWifiLevel); - pw.print(" mWifiSsid="); - pw.println(mWifiSsid); - pw.println(String.format(" mWifiIconId=0x%08x/%s", - mWifiIconId, getResourceName(mWifiIconId))); - pw.println(String.format(" mQSWifiIconId=0x%08x/%s", - mQSWifiIconId, getResourceName(mQSWifiIconId))); - pw.print(" mWifiActivity="); - pw.println(mWifiActivity); - - if (mWimaxSupported) { - pw.println(" - wimax ------"); - pw.print(" mIsWimaxEnabled="); pw.println(mIsWimaxEnabled); - pw.print(" mWimaxConnected="); pw.println(mWimaxConnected); - pw.print(" mWimaxIdle="); pw.println(mWimaxIdle); - pw.println(String.format(" mWimaxIconId=0x%08x/%s", - mWimaxIconId, getResourceName(mWimaxIconId))); - pw.println(String.format(" mWimaxSignal=%d", mWimaxSignal)); - pw.println(String.format(" mWimaxState=%d", mWimaxState)); - pw.println(String.format(" mWimaxExtraState=%d", mWimaxExtraState)); + protected I getIcons() { + return (I) mCurrentState.iconGroup; } - pw.println(" - Bluetooth ----"); - pw.print(" mBtReverseTethered="); - pw.println(mBluetoothTethered); + /** + * Saves the last state of any changes, so we can log the current + * and last value of any state data. + */ + protected void recordLast() { + mHistory[mHistoryIndex++ & (HISTORY_SIZE - 1)].copyFrom(mLastState); + } - pw.println(" - connectivity ------"); - pw.print(" mInetCondition="); - pw.println(mInetCondition); + public void dump(PrintWriter pw) { + pw.println(" - " + mTag + " -----"); + pw.println(" Current State: " + mCurrentState); + if (RECORD_HISTORY) { + // Count up the states that actually contain time stamps, and only display those. + int size = 0; + for (int i = 0; i < HISTORY_SIZE; i++) { + if (mHistory[i].time != 0) size++; + } + // Print out the previous states in ordered number. + for (int i = mHistoryIndex + HISTORY_SIZE - 1; + i >= mHistoryIndex + HISTORY_SIZE - size; i--) { + pw.println(" Previous State(" + (mHistoryIndex + HISTORY_SIZE - i) + ": " + + mHistory[i & (HISTORY_SIZE - 1)]); + } + } + } - pw.println(" - icons ------"); - pw.print(" mLastPhoneSignalIconId=0x"); - pw.print(Integer.toHexString(mLastPhoneSignalIconId)); - pw.print("/"); - pw.println(getResourceName(mLastPhoneSignalIconId)); - pw.print(" mLastDataDirectionIconId=0x"); - pw.print(Integer.toHexString(mLastDataDirectionIconId)); - pw.print("/"); - pw.println(getResourceName(mLastDataDirectionIconId)); - pw.print(" mLastWifiIconId=0x"); - pw.print(Integer.toHexString(mLastWifiIconId)); - pw.print("/"); - pw.println(getResourceName(mLastWifiIconId)); - pw.print(" mLastCombinedSignalIconId=0x"); - pw.print(Integer.toHexString(mLastCombinedSignalIconId)); - pw.print("/"); - pw.println(getResourceName(mLastCombinedSignalIconId)); - pw.print(" mLastDataTypeIconId=0x"); - pw.print(Integer.toHexString(mLastDataTypeIconId)); - pw.print("/"); - pw.println(getResourceName(mLastDataTypeIconId)); - pw.print(" mLastCombinedLabel="); - pw.print(mLastCombinedLabel); - pw.println(""); - } + /** + * Trigger callbacks based on current state. The callbacks should be completely + * based on current state, and only need to be called in the scenario where + * mCurrentState != mLastState. + */ + public abstract void notifyListeners(); + + /** + * Generate a blank T. + */ + public abstract T cleanState(); + + /* + * Holds icons for a given state. Arrays are generally indexed as inet + * state (full connectivity or not) first, and second dimension as + * signal strength. + */ + static class IconGroup { + final int[][] mSbIcons; + final int[][] mQsIcons; + final int[] mContentDesc; + final int mSbNullState; + final int mQsNullState; + final int mSbDiscState; + final int mQsDiscState; + final int mDiscContentDesc; + // For logging. + final String mName; + + public IconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc, + int sbNullState, int qsNullState, int sbDiscState, int qsDiscState, + int discContentDesc) { + mName = name; + mSbIcons = sbIcons; + mQsIcons = qsIcons; + mContentDesc = contentDesc; + mSbNullState = sbNullState; + mQsNullState = qsNullState; + mSbDiscState = sbDiscState; + mQsDiscState = qsDiscState; + mDiscContentDesc = discContentDesc; + } - private String getResourceName(int resId) { - if (resId != 0) { - final Resources res = mContext.getResources(); - try { - return res.getResourceName(resId); - } catch (android.content.res.Resources.NotFoundException ex) { - return "(unknown)"; + @Override + public String toString() { + return "IconGroup(" + mName + ")"; } - } else { - return "(null)"; } - } - private boolean mDemoMode; - private int mDemoInetCondition; - private int mDemoWifiLevel; - private int mDemoDataTypeIconId; - private int mDemoQSDataTypeIconId; - private int mDemoMobileLevel; - - @Override - public void dispatchDemoCommand(String command, Bundle args) { - if (!mDemoMode && command.equals(COMMAND_ENTER)) { - mDemoMode = true; - mDemoWifiLevel = mWifiLevel; - mDemoInetCondition = mInetCondition; - mDemoDataTypeIconId = mDataTypeIconId; - mDemoQSDataTypeIconId = mQSDataTypeIconId; - mDemoMobileLevel = mLastSignalLevel; - } else if (mDemoMode && command.equals(COMMAND_EXIT)) { - mDemoMode = false; - for (SignalCluster cluster : mSignalClusters) { - refreshSignalCluster(cluster); + static class State { + boolean connected; + boolean enabled; + boolean activityIn; + boolean activityOut; + int level; + IconGroup iconGroup; + int inetCondition; + int rssi; // Only for logging. + + // Not used for comparison, just used for logging. + long time; + + public void copyFrom(State state) { + connected = state.connected; + enabled = state.enabled; + level = state.level; + iconGroup = state.iconGroup; + inetCondition = state.inetCondition; + activityIn = state.activityIn; + activityOut = state.activityOut; + rssi = state.rssi; + time = state.time; } - refreshViews(); - } else if (mDemoMode && command.equals(COMMAND_NETWORK)) { - String airplane = args.getString("airplane"); - if (airplane != null) { - boolean show = airplane.equals("show"); - for (SignalCluster cluster : mSignalClusters) { - cluster.setIsAirplaneMode(show, TelephonyIcons.FLIGHT_MODE_ICON); + + @Override + public String toString() { + if (time != 0) { + StringBuilder builder = new StringBuilder(); + toString(builder); + return builder.toString(); + } else { + return "Empty " + getClass().getSimpleName(); } } - String fully = args.getString("fully"); - if (fully != null) { - mDemoInetCondition = Boolean.parseBoolean(fully) ? 1 : 0; - } - String wifi = args.getString("wifi"); - if (wifi != null) { - boolean show = wifi.equals("show"); - String level = args.getString("level"); - if (level != null) { - mDemoWifiLevel = level.equals("null") ? -1 - : Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1); - } - int iconId = mDemoWifiLevel < 0 ? R.drawable.stat_sys_wifi_signal_null - : WifiIcons.WIFI_SIGNAL_STRENGTH[mDemoInetCondition][mDemoWifiLevel]; - for (SignalCluster cluster : mSignalClusters) { - cluster.setWifiIndicators( - show, - iconId, - "Demo"); - } - refreshViews(); + + protected void toString(StringBuilder builder) { + builder.append("connected=").append(connected).append(',') + .append("enabled=").append(enabled).append(',') + .append("level=").append(level).append(',') + .append("inetCondition=").append(inetCondition).append(',') + .append("iconGroup=").append(iconGroup).append(',') + .append("activityIn=").append(activityIn).append(',') + .append("activityOut=").append(activityOut).append(',') + .append("rssi=").append(rssi).append(',') + .append("lastModified=").append(DateFormat.format("MM-dd hh:mm:ss", time)); } - String mobile = args.getString("mobile"); - if (mobile != null) { - boolean show = mobile.equals("show"); - String datatype = args.getString("datatype"); - if (datatype != null) { - mDemoDataTypeIconId = - datatype.equals("1x") ? TelephonyIcons.ICON_1X : - datatype.equals("3g") ? TelephonyIcons.ICON_3G : - datatype.equals("4g") ? TelephonyIcons.ICON_4G : - datatype.equals("e") ? R.drawable.stat_sys_data_fully_connected_e : - datatype.equals("g") ? R.drawable.stat_sys_data_fully_connected_g : - datatype.equals("h") ? R.drawable.stat_sys_data_fully_connected_h : - datatype.equals("lte") ? TelephonyIcons.ICON_LTE : - datatype.equals("roam") ? TelephonyIcons.ROAMING_ICON : - 0; - mDemoQSDataTypeIconId = - datatype.equals("1x") ? TelephonyIcons.QS_ICON_1X : - datatype.equals("3g") ? TelephonyIcons.QS_ICON_3G : - datatype.equals("4g") ? TelephonyIcons.QS_ICON_4G : - datatype.equals("e") ? R.drawable.ic_qs_signal_e : - datatype.equals("g") ? R.drawable.ic_qs_signal_g : - datatype.equals("h") ? R.drawable.ic_qs_signal_h : - datatype.equals("lte") ? TelephonyIcons.QS_ICON_LTE : - datatype.equals("roam") ? R.drawable.ic_qs_signal_r : - 0; - } - int[][] icons = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH; - String level = args.getString("level"); - if (level != null) { - mDemoMobileLevel = level.equals("null") ? -1 - : Math.min(Integer.parseInt(level), icons[0].length - 1); - } - int iconId = mDemoMobileLevel < 0 ? R.drawable.stat_sys_signal_null : - icons[mDemoInetCondition][mDemoMobileLevel]; - for (SignalCluster cluster : mSignalClusters) { - cluster.setMobileDataIndicators( - show, - iconId, - mDemoDataTypeIconId, - "Demo", - "Demo", - isTypeIconWide(mDemoDataTypeIconId)); + + @Override + public boolean equals(Object o) { + if (!o.getClass().equals(getClass())) { + return false; } - refreshViews(); + State other = (State) o; + return other.connected == connected + && other.enabled == enabled + && other.level == level + && other.inetCondition == inetCondition + && other.iconGroup == iconGroup + && other.activityIn == activityIn + && other.activityOut == activityOut + && other.rssi == rssi; } } } + + public interface SignalCluster { + void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription); + + void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon, + String contentDescription, String typeContentDescription, boolean isTypeIconWide); + + void setIsAirplaneMode(boolean is, int airplaneIcon, int contentDescription); + } + + public interface EmergencyListener { + void setEmergencyCallsOnly(boolean emergencyOnly); + } + + public interface CarrierLabelListener { + void setCarrierLabel(String label); + } + + @VisibleForTesting + static class Config { + boolean showAtLeastThreeGees = false; + boolean alwaysShowCdmaRssi = false; + boolean show4gForLte = false; + boolean hspaDataDistinguishable; + + static Config readConfig(Context context) { + Config config = new Config(); + Resources res = context.getResources(); + + config.showAtLeastThreeGees = res.getBoolean(R.bool.config_showMin3G); + config.alwaysShowCdmaRssi = + res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi); + config.show4gForLte = res.getBoolean(R.bool.config_show4GForLTE); + config.hspaDataDistinguishable = + res.getBoolean(R.bool.config_hspa_data_distinguishable); + return config; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java index 1f2b91895a75..4091619aa879 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java @@ -17,11 +17,16 @@ package com.android.systemui.statusbar.policy; import com.android.systemui.R; +import com.android.systemui.statusbar.policy.NetworkControllerImpl.MobileSignalController.MobileIconGroup; class TelephonyIcons { //***** Signal strength icons + static final int TELEPHONY_NUM_LEVELS = 5; + //GSM/UMTS + static final int TELEPHONY_NO_NETWORK = R.drawable.stat_sys_signal_null; + static final int[][] TELEPHONY_SIGNAL_STRENGTH = { { R.drawable.stat_sys_signal_0, R.drawable.stat_sys_signal_1, @@ -35,6 +40,8 @@ class TelephonyIcons { R.drawable.stat_sys_signal_4_fully } }; + static final int QS_TELEPHONY_NO_NETWORK = R.drawable.ic_qs_signal_no_signal; + static final int[][] QS_TELEPHONY_SIGNAL_STRENGTH = { { R.drawable.ic_qs_signal_0, R.drawable.ic_qs_signal_1, @@ -66,8 +73,6 @@ class TelephonyIcons { R.drawable.ic_qs_signal_r }; - static final int[][] DATA_SIGNAL_STRENGTH = TELEPHONY_SIGNAL_STRENGTH; - //***** Data connection icons //GSM/UMTS @@ -191,6 +196,9 @@ class TelephonyIcons { static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode; static final int ROAMING_ICON = R.drawable.stat_sys_data_fully_connected_roam; static final int ICON_LTE = R.drawable.stat_sys_data_fully_connected_lte; + static final int ICON_G = R.drawable.stat_sys_data_fully_connected_g; + static final int ICON_E = R.drawable.stat_sys_data_fully_connected_e; + static final int ICON_H = R.drawable.stat_sys_data_fully_connected_h; static final int ICON_3G = R.drawable.stat_sys_data_fully_connected_3g; static final int ICON_4G = R.drawable.stat_sys_data_fully_connected_4g; static final int ICON_1X = R.drawable.stat_sys_data_fully_connected_1x; @@ -199,5 +207,137 @@ class TelephonyIcons { static final int QS_ICON_3G = R.drawable.ic_qs_signal_3g; static final int QS_ICON_4G = R.drawable.ic_qs_signal_4g; static final int QS_ICON_1X = R.drawable.ic_qs_signal_1x; + + static final MobileIconGroup THREE_G = new MobileIconGroup( + "3G", + TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH, + TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + TelephonyIcons.TELEPHONY_NO_NETWORK, + TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + R.string.accessibility_data_connection_3g, + TelephonyIcons.ICON_3G, + true, + TelephonyIcons.QS_DATA_3G + ); + + static final MobileIconGroup UNKNOWN = new MobileIconGroup( + "Unknown", + TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH, + TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + TelephonyIcons.TELEPHONY_NO_NETWORK, + TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + 0, 0, false, new int[2] + ); + + static final MobileIconGroup E = new MobileIconGroup( + "E", + TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH, + TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + TelephonyIcons.TELEPHONY_NO_NETWORK, + TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + R.string.accessibility_data_connection_edge, + TelephonyIcons.ICON_E, + false, + TelephonyIcons.QS_DATA_E + ); + + static final MobileIconGroup ONE_X = new MobileIconGroup( + "1X", + TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH, + TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + TelephonyIcons.TELEPHONY_NO_NETWORK, + TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + R.string.accessibility_data_connection_cdma, + TelephonyIcons.ICON_1X, + true, + TelephonyIcons.QS_DATA_1X + ); + + static final MobileIconGroup G = new MobileIconGroup( + "G", + TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH, + TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + TelephonyIcons.TELEPHONY_NO_NETWORK, + TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + R.string.accessibility_data_connection_gprs, + TelephonyIcons.ICON_G, + false, + TelephonyIcons.QS_DATA_G + ); + + static final MobileIconGroup H = new MobileIconGroup( + "H", + TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH, + TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + TelephonyIcons.TELEPHONY_NO_NETWORK, + TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + R.string.accessibility_data_connection_3_5g, + TelephonyIcons.ICON_H, + false, + TelephonyIcons.QS_DATA_H + ); + + static final MobileIconGroup FOUR_G = new MobileIconGroup( + "4G", + TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH, + TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + TelephonyIcons.TELEPHONY_NO_NETWORK, + TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + R.string.accessibility_data_connection_4g, + TelephonyIcons.ICON_4G, + true, + TelephonyIcons.QS_DATA_4G + ); + + static final MobileIconGroup LTE = new MobileIconGroup( + "LTE", + TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH, + TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + TelephonyIcons.TELEPHONY_NO_NETWORK, + TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + R.string.accessibility_data_connection_lte, + TelephonyIcons.ICON_LTE, + true, + TelephonyIcons.QS_DATA_LTE + ); + + static final MobileIconGroup ROAMING = new MobileIconGroup( + "Roaming", + TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING, + TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + TelephonyIcons.TELEPHONY_NO_NETWORK, + TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + R.string.accessibility_data_connection_roaming, + TelephonyIcons.ROAMING_ICON, + false, + TelephonyIcons.QS_DATA_R + ); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java index 49af97923ecc..c56646fc7740 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java @@ -45,5 +45,8 @@ class WifiIcons { R.drawable.ic_qs_wifi_full_4 } }; + static final int QS_WIFI_NO_NETWORK = R.drawable.ic_qs_wifi_no_network; + static final int WIFI_NO_NETWORK = R.drawable.stat_sys_wifi_signal_null; + static final int WIFI_LEVEL_COUNT = WIFI_SIGNAL_STRENGTH[0].length; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java deleted file mode 100644 index 48778282972e..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.statusbar.policy; - -import com.android.systemui.statusbar.policy.TelephonyIcons; - -class WimaxIcons { - static final int[][] WIMAX_SIGNAL_STRENGTH = TelephonyIcons.DATA_SIGNAL_STRENGTH; - - static final int WIMAX_DISCONNECTED = WIMAX_SIGNAL_STRENGTH[0][0]; - - static final int WIMAX_IDLE = WIMAX_DISCONNECTED; // XXX: unclear if we need a different icon -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java index 10cffc49574b..49fe1e3f0c34 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java @@ -17,6 +17,7 @@ import android.util.Log; import com.android.internal.telephony.cdma.EriInfo; import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback; +import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config; import com.android.systemui.statusbar.policy.NetworkControllerImpl.SignalCluster; import org.mockito.ArgumentCaptor; @@ -44,6 +45,7 @@ public class NetworkControllerBaseTest extends AndroidTestCase { protected ConnectivityManager mMockCm; protected WifiManager mMockWm; protected TelephonyManager mMockTm; + protected Config mConfig; @Override protected void setUp() throws Exception { @@ -59,16 +61,19 @@ public class NetworkControllerBaseTest extends AndroidTestCase { mSignalStrength = mock(SignalStrength.class); mServiceState = mock(ServiceState.class); - mSignalCluster = mock(SignalCluster.class); - mNetworkSignalChangedCallback = mock(NetworkSignalChangedCallback.class); + mConfig = new Config(); + mConfig.hspaDataDistinguishable = true; mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, - mock(AccessPointController.class), mock(MobileDataController.class)); + mConfig, mock(AccessPointControllerImpl.class), + mock(MobileDataControllerImpl.class)); setupNetworkController(); } protected void setupNetworkController() { - mPhoneStateListener = mNetworkController.mPhoneStateListener; + mPhoneStateListener = mNetworkController.mMobileSignalController.mPhoneStateListener; + mSignalCluster = mock(SignalCluster.class); + mNetworkSignalChangedCallback = mock(NetworkSignalChangedCallback.class); mNetworkController.addSignalCluster(mSignalCluster); mNetworkController.addNetworkSignalChangedCallback(mNetworkSignalChangedCallback); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java index af053094352f..bb2ff7c67a9a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java @@ -18,7 +18,8 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { Mockito.when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false); // Create a new NetworkController as this is currently handled in constructor. mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, - mock(AccessPointController.class), mock(MobileDataController.class)); + mConfig, mock(AccessPointControllerImpl.class), + mock(MobileDataControllerImpl.class)); setupNetworkController(); verifyLastMobileDataIndicators(false, 0, 0); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java index 4ffdff280b44..7f0a8f4dd1ae 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java @@ -6,8 +6,6 @@ import android.net.NetworkInfo; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; -import com.android.systemui.R; - import org.mockito.ArgumentCaptor; import org.mockito.Mockito; @@ -16,14 +14,10 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest { private static final int MIN_RSSI = -100; private static final int MAX_RSSI = -55; - // TODO: Move this into WifiIcons, remove all R.drawable from NetworkControllerImpl. - private static final int NULL_SIGNAL = R.drawable.stat_sys_wifi_signal_null; - private static final int QS_NO_NET = R.drawable.ic_qs_wifi_no_network; - public void testWifiIcon() { String testSsid = "Test SSID"; setWifiEnabled(true); - verifyLastWifiIcon(false, NULL_SIGNAL); + verifyLastWifiIcon(false, WifiIcons.WIFI_NO_NETWORK); setWifiState(true, testSsid); verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[0][0]); @@ -42,10 +36,10 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest { String testSsid = "Test SSID"; setWifiEnabled(false); - verifyLastQsWifiIcon(false, false, 0, null); + verifyLastQsWifiIcon(false, false, WifiIcons.QS_WIFI_NO_NETWORK, null); setWifiEnabled(true); - verifyLastQsWifiIcon(true, false, QS_NO_NET, null); + verifyLastQsWifiIcon(true, false, WifiIcons.QS_WIFI_NO_NETWORK, null); setWifiState(true, testSsid); for (int testLevel = 0; testLevel < WifiIcons.WIFI_LEVEL_COUNT; testLevel++) { @@ -118,8 +112,7 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest { protected void setWifiActivity(int activity) { // TODO: Not this, because this variable probably isn't sticking around. - mNetworkController.mWifiActivity = activity; - mNetworkController.refreshViews(); + mNetworkController.mWifiSignalController.setActivity(activity); } protected void setWifiLevel(int level) { |