From d2263cd9db36d5f74a124c5ffaf8594ef702408f Mon Sep 17 00:00:00 2001 From: Jason Monk Date: Mon, 10 Nov 2014 14:22:56 -0500 Subject: [PATCH] SysUI: Refactor the NetworkControllerImpl Minimal changes to interface/callbacks, all of the changes are internal and prepare for MSIM. Separate out AccessPoint and MobileData from the NetworkController interface to give some space. A SignalController class has been created as a base for both WifiSignalController and MobileSignalController, both of which internally handle the state of their respective connectivity and only reach up into the NetworkControllerImpl when completely necessary (such as for combined carrier label). Bug: 18222975 Change-Id: I75b954bbece187371cdb8571dd8420e7d2cad978 --- .../systemui/qs/tiles/CellularTile.java | 14 +- .../qs/tiles/DataUsageDetailView.java | 3 +- .../android/systemui/qs/tiles/WifiTile.java | 17 +- .../systemui/statusbar/SignalClusterView.java | 6 +- .../statusbar/phone/PhoneStatusBar.java | 28 +- .../systemui/statusbar/phone/QSTileHost.java | 2 +- ...er.java => AccessPointControllerImpl.java} | 17 +- .../AccessibilityContentDescriptions.java | 8 +- ...ler.java => MobileDataControllerImpl.java} | 14 +- .../statusbar/policy/NetworkController.java | 72 +- .../policy/NetworkControllerImpl.java | 2542 ++++++++--------- .../statusbar/policy/TelephonyIcons.java | 144 +- .../systemui/statusbar/policy/WifiIcons.java | 3 + .../systemui/statusbar/policy/WimaxIcons.java | 27 - .../policy/NetworkControllerBaseTest.java | 13 +- .../policy/NetworkControllerSignalTest.java | 3 +- .../policy/NetworkControllerWifiTest.java | 15 +- 17 files changed, 1482 insertions(+), 1446 deletions(-) rename packages/SystemUI/src/com/android/systemui/statusbar/policy/{AccessPointController.java => AccessPointControllerImpl.java} (95%) rename packages/SystemUI/src/com/android/systemui/statusbar/policy/{MobileDataController.java => MobileDataControllerImpl.java} (95%) delete mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java 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 178590be3b23b..80ddd4a8bec1d 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 { "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 { @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 { @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 { @Override public void setToggleState(boolean state) { - mController.setMobileDataEnabled(state); + mDataController.setMobileDataEnabled(state); } @Override @@ -217,7 +221,7 @@ public class CellularTile extends QSTile { 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 7bdb58f2daa7b..eb816b759c91a 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 7aa884effe7ab..4fb1189dee905 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 { 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 { 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 { @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 { }; 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 { 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 { 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 9154a487e8ac7..418c57f8f15c4 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 3b2d3cb0b13c3..9a1ac4949272a 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 45a138610b1c7..8ce608c016b53 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 similarity index 95% rename from packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointController.java rename to packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java index 0a385d72666bc..6fec97e09aacf 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 7ac2a986c75da..b7c74e3afadf2 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 similarity index 95% rename from packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataController.java rename to packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataControllerImpl.java index 33d68bf37f09b..20f0a83d38b1f 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 bb29d01e25575..b024f58cbd278 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 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 AccessPoint { - public static final int NO_NETWORK = -1; // see WifiManager + /** + * Tracks mobile data support and usage. + */ + public interface MobileDataController { + boolean isMobileDataSupported(); + boolean isMobileDataEnabled(); + void setMobileDataEnabled(boolean enabled); + DataUsageInfo getDataUsageInfo(); - 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; + 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 07762a4604c05..5a97c75e313b3 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 + 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; - // 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; + private static final int INET_CONDITION_THRESHOLD = 50; - String mContentDescriptionPhoneSignal; - String mContentDescriptionWifi; - String mContentDescriptionWimax; - String mContentDescriptionCombinedSignal; - String mContentDescriptionDataType; + private final Context mContext; + private final TelephonyManager mPhone; + private final WifiManager mWifiManager; + private final ConnectivityManager mConnectivityManager; + private final boolean mHasMobileDataFeature; - // 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; + // 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 mCombinedLabelViews = new ArrayList(); - ArrayList mMobileLabelViews = new ArrayList(); - ArrayList mWifiLabelViews = new ArrayList(); - ArrayList mEmergencyViews = new ArrayList<>(); - ArrayList mSignalClusters = new ArrayList(); - ArrayList mSignalsChangedCallbacks = + // All the callbacks. + private ArrayList mEmergencyListeners = new ArrayList(); + private ArrayList mCarrierListeners = + new ArrayList(); + private ArrayList mSignalClusters = new ArrayList(); + private ArrayList mSignalsChangedCallbacks = new ArrayList(); - 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; /** * 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); } - @Override - public boolean canConfigWifi() { - return mAccessPoints.canConfigWifi(); + private void unregisterListeners() { + mMobileSignalController.unregisterListener(); + mContext.unregisterReceiver(this); } @Override - public void onUserSwitched(int newUserId) { - mAccessPoints.onUserSwitched(newUserId); + public AccessPointController getAccessPointController() { + return mAccessPoints; + } + + @Override + 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,60 +213,46 @@ public class NetworkControllerImpl extends BroadcastReceiver return mPhone.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE; } + public String getMobileNetworkName() { + return mMobileSignalController.mCurrentState.networkName; + } + public boolean isEmergencyOnly() { - return (mServiceState != null && mServiceState.isEmergencyOnly()); + return mMobileSignalController.isEmergencyOnly(); } - public void addCombinedLabelView(TextView v) { - mCombinedLabelViews.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 addMobileLabelView(TextView v) { - mMobileLabelViews.add(v); - } - - public void addWifiLabelView(TextView v) { - mWifiLabelViews.add(v); - } - - 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) { mSignalsChangedCallbacks.remove(cb); } - @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() { @@ -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); } @@ -362,733 +271,80 @@ public class NetworkControllerImpl extends BroadcastReceiver }.execute(); } - @Override - public DataUsageInfo getDataUsageInfo() { - final DataUsageInfo info = mMobileDataController.getDataUsageInfo(); - if (info != null) { - info.carrier = mNetworkName; - } - return info; - } - - @Override - public boolean isMobileDataSupported() { - return mMobileDataController.isMobileDataSupported(); - } - - @Override - public boolean isMobileDataEnabled() { - return mMobileDataController.isMobileDataEnabled(); - } - - @Override - public void setMobileDataEnabled(boolean enabled) { - mMobileDataController.setMobileDataEnabled(enabled); - } - - private boolean isTypeIconWide(int iconId) { - return TelephonyIcons.ICON_LTE == iconId || TelephonyIcons.ICON_1X == iconId - || TelephonyIcons.ICON_3G == iconId || TelephonyIcons.ICON_4G == iconId; - } - - 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; - } - - 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); - } - - 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)); - } 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)); - } - } - cb.onAirplaneModeChanged(mAirplaneMode); - } - - public void setStackedMode(boolean stacked) { - mDataAndWifiStacked = true; - } - @Override public void onReceive(Context context, Intent intent) { + if (CHATTY) { + Log.d(TAG, "onReceive: 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)) { + if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE) || + action.equals(ConnectivityManager.INET_CONDITION_ACTION)) { updateConnectivity(intent); - refreshViews(); + refreshCarrierLabel(); } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { refreshLocale(); - refreshViews(); + refreshCarrierLabel(); } 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(); + updateAirplaneMode(false); + refreshCarrierLabel(); } + mWifiSignalController.handleBroadcast(intent); + mMobileSignalController.handleBroadcast(intent); } - - // ===== Telephony ============================================================== - - 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(); + 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 void onServiceStateChanged(ServiceState state) { - if (DEBUG) { - Log.d(TAG, "onServiceStateChanged voiceState=" + state.getVoiceRegState() - + " dataState=" + state.getDataRegState()); - } - mServiceState = state; - updateTelephonySignalStrength(); - updateDataNetType(); - updateDataIcon(); - refreshViews(); - } - - @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(); - } - } - - @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(); - } - - @Override - public void onDataActivity(int direction) { - if (DEBUG) { - Log.d(TAG, "onDataActivity: direction=" + direction); - } - mDataActivity = direction; - updateDataIcon(); - refreshViews(); - } - }; - - 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; - } - else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) { - mSimState = IccCardConstants.State.PUK_REQUIRED; - } - else { - mSimState = IccCardConstants.State.NETWORK_LOCKED; - } - } else { - mSimState = IccCardConstants.State.UNKNOWN; - } - 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; - } - } else { - retVal = false; - } - 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; - } - - 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(); - } - - 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); - } + Locale current = mContext.getResources().getConfiguration().locale; + if (current.equals(mLocale)) { + mLocale = current; + notifyAllListeners(); } } - private int inetConditionForNetwork(int networkType) { - return (mInetCondition == 1 && mConnectedNetworkType == networkType) ? 1 : 0; + /** + * 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 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); - } 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; - 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; - } - } + private void notifyAllListeners() { + // Something changed, trigger everything! + notifyAirplaneCallbacks(); + mMobileSignalController.notifyListeners(); + mWifiSignalController.notifyListeners(); + } - if (isRoaming()) { - mDataTypeIconId = TelephonyIcons.ROAMING_ICON; - mQSDataTypeIconId = TelephonyIcons.QS_DATA_R[mInetCondition]; + 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); } } - 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; - } - } - } - return false; - } - - private boolean isRoaming() { - if (isCdma()) { - return isCdmaEri(); - } else { - return mServiceState != null && mServiceState.getRoaming(); - } - } - - 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]; - break; - case TelephonyManager.DATA_ACTIVITY_INOUT: - iconId = mDataIconList[3]; - break; - case TelephonyManager.DATA_ACTIVITY_DORMANT: - default: - iconId = mDataIconList[0]; - break; - } - } else { - iconId = 0; - visible = false; - } - } - - mDataDirectionIconId = iconId; - mDataConnected = visible; - } - - 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); - } - str.append(spn); - something = true; - } - if (something) { - mNetworkName = str.toString(); - } else { - mNetworkName = mNetworkNameDefault; - } - } - - // ===== 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(TAG, "Failed to connect to wifi"); - } - break; - case WifiManager.DATA_ACTIVITY_NOTIFICATION: - if (msg.arg1 != mWifiActivity) { - mWifiActivity = msg.arg1; - refreshViews(); - } - break; - default: - //Ignore - break; - } - } - } - - 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(); - } - if (info != null) { - mWifiSsid = huntForSsid(info); - } else { - mWifiSsid = null; - } - } 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(); - } - - 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); - } - } - - 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 networks = mWifiManager.getConfiguredNetworks(); - for (WifiConfiguration net : networks) { - if (net.networkId == info.getNetworkId()) { - return net.SSID; - } - } - return null; - } - - - // ===== 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(); - } - - 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]); - } else { - mWimaxIconId = WimaxIcons.WIMAX_DISCONNECTED; - mContentDescriptionWimax = mContext.getString(R.string.accessibility_no_wimax); - } - } else { - mWimaxIconId = 0; - } - } - - // ===== Full or limited Internet connectivity ================================== - + /** + * Update the Inet conditions and what network we are connected to. + */ private void updateConnectivity(Intent intent) { - if (CHATTY) { - Log.d(TAG, "updateConnectivity: intent=" + intent); - } - final NetworkInfo info = mConnectivityManager.getActiveNetworkInfo(); // Are we connected at all, by any interface? @@ -1108,7 +364,7 @@ public class NetworkControllerImpl extends BroadcastReceiver Log.d(TAG, "updateConnectivity: connectionStatus=" + connectionStatus); } - mInetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0); + mInetCondition = connectionStatus > INET_CONDITION_THRESHOLD; if (info != null && info.getType() == ConnectivityManager.TYPE_BLUETOOTH) { mBluetoothTethered = info.isConnected(); @@ -1117,376 +373,68 @@ public class NetworkControllerImpl extends BroadcastReceiver } // We want to update all the icons, all at once, for any condition change - updateDataNetType(); - updateWimaxIcons(); - updateDataIcon(); - updateTelephonySignalStrength(); - updateWifiIcons(); + mMobileSignalController.setInetCondition(mInetCondition ? 1 : 0, + inetConditionForNetwork(mMobileSignalController.getNetworkType(), mInetCondition)); + mWifiSignalController.setInetCondition( + inetConditionForNetwork(mWifiSignalController.getNetworkType(), mInetCondition)); } - - // ===== Update the views ======================================================= - - void refreshViews() { + /** + * Recalculate and update the carrier label. + */ + void refreshCarrierLabel() { Context context = mContext; - int combinedSignalIconId = 0; - String combinedLabel = ""; - String wifiLabel = ""; - String mobileLabel = ""; - int N; - final boolean emergencyOnly = isEmergencyOnly(); + WifiSignalController.WifiState wifiState = mWifiSignalController.getState(); + MobileSignalController.MobileState mobileState = mMobileSignalController.getState(); + String label = mMobileSignalController.getLabel("", mConnected, mHasMobileDataFeature); - 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; - } else { - // Tablets, basically - mobileLabel = ""; - } - } else { - mobileLabel - = context.getString(R.string.status_bar_settings_signal_meter_disconnected); - } - - // 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; - } + // 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); } - if (mWifiConnected) { - if (mWifiSsid == null) { - wifiLabel = context.getString(R.string.status_bar_settings_signal_meter_wifi_nossid); - } else { - wifiLabel = mWifiSsid; - if (DEBUG) { - wifiLabel += "xxxxXXXXxxxxXXXX"; - } - } - - 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); - } + final boolean ethernetConnected = + (mConnectedNetworkType == ConnectivityManager.TYPE_ETHERNET); + if (ethernetConnected && !mHasMobileDataFeature) { + label = context.getString(R.string.ethernet_label); } - if (mBluetoothTethered) { - combinedLabel = mContext.getString(R.string.bluetooth_tethered); - combinedSignalIconId = mBluetoothTetherIconId; - mContentDescriptionCombinedSignal = mContext.getString( - R.string.accessibility_bluetooth_tether); - } - - final boolean ethernetConnected = (mConnectedNetworkType == ConnectivityManager.TYPE_ETHERNET); - if (ethernetConnected) { - combinedLabel = context.getString(R.string.ethernet_label); - } - - 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; - + if (mAirplaneMode && (!mobileState.connected && !mobileState.isEmergency)) { // combined values from connected wifi take precedence over airplane mode - if (mWifiConnected) { + if (wifiState.connected && mHasMobileDataFeature) { // Suppress "No internet connection." from mobile if wifi connected. - mobileLabel = ""; + label = ""; } 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; - } - mContentDescriptionCombinedSignal = mContentDescriptionPhoneSignal; - combinedSignalIconId = mDataSignalIconId; - } - } - 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; - - int inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_MOBILE); - - mDataTypeIconId = 0; - mQSDataTypeIconId = 0; - if (isRoaming()) { - mDataTypeIconId = TelephonyIcons.ROAMING_ICON; - mQSDataTypeIconId = TelephonyIcons.QS_DATA_R[mInetCondition]; + 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); } - 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)); - } - - // 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); - } - } - - if (mLastAirplaneMode != mAirplaneMode) { - mLastAirplaneMode = mAirplaneMode; - } - - if (mLastLocale != mLocale) { - mLastLocale = mLocale; - } - - // the phone icon on phones - if (mLastPhoneSignalIconId != mPhoneSignalIconId) { - mLastPhoneSignalIconId = mPhoneSignalIconId; - } - - // the data icon on phones - if (mLastDataDirectionIconId != mDataDirectionIconId) { - mLastDataDirectionIconId = mDataDirectionIconId; - } - - // the wifi icon on phones - if (mLastWifiIconId != mWifiIconId) { - mLastWifiIconId = mWifiIconId; - } - - if (mLastInetCondition != mInetCondition) { - mLastInetCondition = mInetCondition; - } - - if (mLastConnectedNetworkType != mConnectedNetworkType) { - mLastConnectedNetworkType = mConnectedNetworkType; - } - - // the wimax icon on phones - if (mLastWimaxIconId != mWimaxIconId) { - mLastWimaxIconId = mWimaxIconId; - } - // the combined data signal icon - if (mLastCombinedSignalIconId != combinedSignalIconId) { - mLastCombinedSignalIconId = combinedSignalIconId; - } - - // the data network type overlay - if (mLastDataTypeIconId != mDataTypeIconId) { - mLastDataTypeIconId = mDataTypeIconId; - } - - // the combinedLabel in the notification panel - if (!mLastCombinedLabel.equals(combinedLabel)) { - mLastCombinedLabel = combinedLabel; - N = mCombinedLabelViews.size(); - for (int i=0; i= 0; } - 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(); + mDemoWifiState.enabled = show; + mWifiSignalController.notifyListeners(); } 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; + 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) { - mDemoMobileLevel = level.equals("null") ? -1 + mDemoMobileState.level = level.equals("null") ? -1 : Math.min(Integer.parseInt(level), icons[0].length - 1); + mDemoMobileState.connected = mDemoMobileState.level >= 0; } - 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)); + mDemoMobileState.enabled = show; + mMobileSignalController.notifyListeners(); + } + refreshCarrierLabel(); + } + } + + static class WifiSignalController extends + SignalController { + private final WifiManager mWifiManager; + private final AsyncChannel mWifiChannel; + private final boolean mHasMobileData; + + public WifiSignalController(Context context, boolean hasMobileData, + List signalCallbacks, + List 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); + } + // 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 + ); + } + + @Override + public WifiState cleanState() { + return new WifiState(); + } + + /** + * {@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); + } + + 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); + } + } + + /** + * 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 { + mCurrentState.ssid = null; + } + } else if (!mCurrentState.connected) { + mCurrentState.ssid = null; } - refreshViews(); + } 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); + } + + notifyListenersIfNecessary(); + } + + 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 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; + } + + @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(); + } + + /** + * 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 WifiManager.DATA_ACTIVITY_NOTIFICATION: + setActivity(msg.arg1); + break; + default: + // Ignore + break; + } + } + } + + static class WifiState extends SignalController.State { + String ssid; + + @Override + public void copyFrom(State s) { + WifiState state = (WifiState) s; + ssid = state.ssid; + super.copyFrom(s); + } + + @Override + protected void toString(StringBuilder builder) { + builder.append("ssid=").append(ssid).append(','); + super.toString(builder); + } + + @Override + public boolean equals(Object o) { + return super.equals(o) + && Objects.equals(((WifiState) o).ssid, ssid); } } } + + static class MobileSignalController extends SignalController { + private final Config mConfig; + private final TelephonyManager mPhone; + private final String mNetworkNameDefault; + private final String mNetworkNameSeparator; + + // @VisibleForDemoMode + Map 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 signalCallbacks, + List 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); + } + + // Now for things that should only be shown when actually using mobile data. + if (isMobileLabel) { + return mobileLabel; + } else { + return mCurrentState.dataConnected ? mobileLabel : currentLabel; + } + } + } + + public int getDataContentDescription() { + return getIcons().mDataContentDescription; + } + + public void setAirplaneMode(boolean airplaneMode) { + mCurrentState.airplaneMode = airplaneMode; + notifyListenersIfNecessary(); + } + + 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); + } + + /** + * 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); + } + + /** + * Stop listening for phone state changes. + */ + public void unregisterListener() { + mPhone.listen(mPhoneStateListener, 0); + } + + /** + * 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(); + + 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); + + 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 { + 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; + } + + 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); + + if (mConfig.show4gForLte) { + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.FOUR_G); + } else { + mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.LTE); + } + } + + /** + * {@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); + } + } + + @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; + } + } + + private boolean isCdma() { + return (mSignalStrength != null) && !mSignalStrength.isGsm(); + } + + public boolean isEmergencyOnly() { + return (mServiceState != null && mServiceState.isEmergencyOnly()); + } + + 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(); + } + } + + 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(); + } + } + + /** + * 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 { + mSimState = IccCardConstants.State.NETWORK_LOCKED; + } + } else { + mSimState = IccCardConstants.State.UNKNOWN; + } + if (DEBUG) Log.d(TAG, "updateSimState: mSimState=" + mSimState); + } + + /** + * 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; + } + } + + /** + * 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 { + 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; + } + } + + if (isRoaming()) { + mCurrentState.iconGroup = TelephonyIcons.ROAMING; + } + if (isEmergencyOnly() != mCurrentState.isEmergency) { + mCurrentState.isEmergency = isEmergencyOnly(); + mNetworkController.recalculateEmergency(); + } + notifyListenersIfNecessary(); + } + + @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(); + } + + @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 + ","); + } + + 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; + updateTelephony(); + } + + @Override + public void onServiceStateChanged(ServiceState state) { + if (DEBUG) { + Log.d(TAG, "onServiceStateChanged voiceState=" + state.getVoiceRegState() + + " dataState=" + state.getDataRegState()); + } + mServiceState = state; + updateTelephony(); + } + + @Override + public void onDataConnectionStateChanged(int state, int networkType) { + if (DEBUG) { + Log.d(TAG, "onDataConnectionStateChanged: state=" + state + + " type=" + networkType); + } + mDataState = state; + mDataNetType = networkType; + updateTelephony(); + } + + @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; + } + } + + static class MobileState extends SignalController.State { + String networkName; + boolean noSim; + boolean dataConnected; + boolean isEmergency; + boolean airplaneMode; + int inetForNetwork; + + @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); + } + + @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); + } + + @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; + } + } + } + + /** + * Common base class for handling signal for both wifi and mobile data. + */ + static abstract class SignalController { + 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 mSignalsChangedCallbacks; + protected final List 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 signalCallbacks, + List 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(); + } + } + } + + public T getState() { + return mCurrentState; + } + + public int getNetworkType() { + return mNetworkType; + } + + public void setInetCondition(int inetCondition) { + mCurrentState.inetCondition = inetCondition; + notifyListenersIfNecessary(); + } + + // @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); + } + + /** + * 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; + } + + 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; + } + } + + /** + * 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; + } + } + + /** + * 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 { + return getIcons().mDiscContentDesc; + } + } + + protected void notifyListenersIfNecessary() { + if (isDirty()) { + saveLastState(); + notifyListeners(); + mNetworkController.refreshCarrierLabel(); + } + } + + /** + * Returns the resource if resId is not 0, and an empty string otherwise. + */ + protected String getStringIfExists(int resId) { + return resId != 0 ? mContext.getString(resId) : ""; + } + + protected I getIcons() { + return (I) mCurrentState.iconGroup; + } + + /** + * 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); + } + + 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)]); + } + } + } + + /** + * 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; + } + + @Override + public String toString() { + return "IconGroup(" + mName + ")"; + } + } + + 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; + } + + @Override + public String toString() { + if (time != 0) { + StringBuilder builder = new StringBuilder(); + toString(builder); + return builder.toString(); + } else { + return "Empty " + getClass().getSimpleName(); + } + } + + 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)); + } + + @Override + public boolean equals(Object o) { + if (!o.getClass().equals(getClass())) { + return false; + } + 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 1f2b91895a759..4091619aa8796 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 49af97923ecc0..c56646fc7740f 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 48778282972ef..0000000000000 --- 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 10cffc49574b4..49fe1e3f0c340 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 af053094352f1..bb2ff7c67a9ad 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 4ffdff280b44b..7f0a8f4dd1ae7 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) {