diff --git a/packages/SystemUI/res/drawable/stat_sys_ethernet.xml b/packages/SystemUI/res/drawable/stat_sys_ethernet.xml
new file mode 100644
index 0000000000000..e765320cb19e2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_ethernet.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
diff --git a/packages/SystemUI/res/drawable/stat_sys_ethernet_fully.xml b/packages/SystemUI/res/drawable/stat_sys_ethernet_fully.xml
new file mode 100644
index 0000000000000..b7b154c28c3e5
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_ethernet_fully.xml
@@ -0,0 +1,24 @@
+
+
+
+
diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml
index c9edef835fd06..69dcad20a33fe 100644
--- a/packages/SystemUI/res/layout/signal_cluster_view.xml
+++ b/packages/SystemUI/res/layout/signal_cluster_view.xml
@@ -33,6 +33,25 @@
android:paddingEnd="6dp"
android:src="@drawable/stat_sys_vpn_ic"
/>
+
+
+
+
WiMAX signal full.
+
+ Ethernet disconnected.
+
+ Ethernet connected.
+
No signal.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index b2bb021be323c..f6629ddbd3254 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -53,18 +53,21 @@ public class SignalClusterView
private boolean mNoSimsVisible = false;
private boolean mVpnVisible = false;
+ private boolean mEthernetVisible = false;
+ private int mEthernetIconId = 0;
private boolean mWifiVisible = false;
private int mWifiStrengthId = 0;
private boolean mIsAirplaneMode = false;
private int mAirplaneIconId = 0;
private int mAirplaneContentDescription;
private String mWifiDescription;
+ private String mEthernetDescription;
private ArrayList mPhoneStates = new ArrayList();
private int mIconTint = Color.WHITE;
private float mDarkIntensity;
- ViewGroup mWifiGroup;
- ImageView mVpn, mWifi, mAirplane, mNoSims, mWifiDark, mNoSimsDark;
+ ViewGroup mEthernetGroup, mWifiGroup;
+ ImageView mVpn, mEthernet, mWifi, mAirplane, mNoSims, mEthernetDark, mWifiDark, mNoSimsDark;
View mWifiAirplaneSpacer;
View mWifiSignalSpacer;
LinearLayout mMobileSignalGroup;
@@ -116,6 +119,9 @@ public class SignalClusterView
super.onAttachedToWindow();
mVpn = (ImageView) findViewById(R.id.vpn);
+ mEthernetGroup = (ViewGroup) findViewById(R.id.ethernet_combo);
+ mEthernet = (ImageView) findViewById(R.id.ethernet);
+ mEthernetDark = (ImageView) findViewById(R.id.ethernet_dark);
mWifiGroup = (ViewGroup) findViewById(R.id.wifi_combo);
mWifi = (ImageView) findViewById(R.id.wifi_signal);
mWifiDark = (ImageView) findViewById(R.id.wifi_signal_dark);
@@ -136,6 +142,8 @@ public class SignalClusterView
@Override
protected void onDetachedFromWindow() {
mVpn = null;
+ mEthernetGroup = null;
+ mEthernet = null;
mWifiGroup = null;
mWifi = null;
mAirplane = null;
@@ -182,6 +190,15 @@ public class SignalClusterView
apply();
}
+ @Override
+ public void setEthernetIndicators(boolean visible, int icon, String contentDescription) {
+ mEthernetVisible = visible;
+ mEthernetIconId = icon;
+ mEthernetDescription = contentDescription;
+
+ apply();
+ }
+
@Override
public void setNoSims(boolean show) {
mNoSimsVisible = show;
@@ -234,6 +251,9 @@ public class SignalClusterView
public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
// Standard group layout onPopulateAccessibilityEvent() implementations
// ignore content description, so populate manually
+ if (mEthernetVisible && mEthernetGroup != null &&
+ mEthernetGroup.getContentDescription() != null)
+ event.getText().add(mEthernetGroup.getContentDescription());
if (mWifiVisible && mWifiGroup != null && mWifiGroup.getContentDescription() != null)
event.getText().add(mWifiGroup.getContentDescription());
for (PhoneState state : mPhoneStates) {
@@ -246,6 +266,10 @@ public class SignalClusterView
public void onRtlPropertiesChanged(int layoutDirection) {
super.onRtlPropertiesChanged(layoutDirection);
+ if (mEthernet != null) {
+ mEthernet.setImageDrawable(null);
+ }
+
if (mWifi != null) {
mWifi.setImageDrawable(null);
}
@@ -277,6 +301,21 @@ public class SignalClusterView
mVpn.setVisibility(mVpnVisible ? View.VISIBLE : View.GONE);
if (DEBUG) Log.d(TAG, String.format("vpn: %s", mVpnVisible ? "VISIBLE" : "GONE"));
+
+ if (mEthernetVisible) {
+ mEthernet.setImageResource(mEthernetIconId);
+ mEthernetDark.setImageResource(mEthernetIconId);
+ mEthernetGroup.setContentDescription(mEthernetDescription);
+ mEthernetGroup.setVisibility(View.VISIBLE);
+ } else {
+ mEthernetGroup.setVisibility(View.GONE);
+ }
+
+ if (DEBUG) Log.d(TAG,
+ String.format("ethernet: %s",
+ (mEthernetVisible ? "VISIBLE" : "GONE")));
+
+
if (mWifiVisible) {
mWifi.setImageResource(mWifiStrengthId);
mWifiDark.setImageResource(mWifiStrengthId);
@@ -327,7 +366,7 @@ public class SignalClusterView
mNoSimsDark.setVisibility(mNoSimsVisible ? View.VISIBLE : View.GONE);
boolean anythingVisible = mNoSimsVisible || mWifiVisible || mIsAirplaneMode
- || anyMobileVisible || mVpnVisible;
+ || anyMobileVisible || mVpnVisible || mEthernetVisible;
setPaddingRelative(0, 0, anythingVisible ? mEndPadding : mEndPaddingNothingVisible, 0);
}
@@ -345,6 +384,7 @@ public class SignalClusterView
setTint(mAirplane, mIconTint);
applyDarkIntensity(mDarkIntensity, mNoSims, mNoSimsDark);
applyDarkIntensity(mDarkIntensity, mWifi, mWifiDark);
+ applyDarkIntensity(mDarkIntensity, mEthernet, mEthernetDark);
for (int i = 0; i < mPhoneStates.size(); i++) {
mPhoneStates.get(i).setIconTint(mIconTint, mDarkIntensity);
}
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 63fcbc54c1bd8..8f86e2d300daf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
@@ -35,4 +35,9 @@ public class AccessibilityContentDescriptions {
};
static final int WIFI_NO_CONNECTION = R.string.accessibility_no_wifi;
+
+ static final int[] ETHERNET_CONNECTION_VALUES = {
+ R.string.accessibility_ethernet_disconnected,
+ R.string.accessibility_ethernet_connected,
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetIcons.java
new file mode 100644
index 0000000000000..b391bd9cf6517
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetIcons.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2015 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.R;
+
+class EthernetIcons {
+ static final int[][] ETHERNET_ICONS = {
+ { R.drawable.stat_sys_ethernet },
+ { R.drawable.stat_sys_ethernet_fully },
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java
new file mode 100644
index 0000000000000..9c044c4b87c9a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 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 android.content.Context;
+import android.net.NetworkCapabilities;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
+import com.android.systemui.statusbar.policy.NetworkControllerImpl.SignalCluster;
+
+import java.util.List;
+import java.util.Objects;
+
+
+public class EthernetSignalController extends
+ SignalController {
+
+ public EthernetSignalController(Context context,
+ List signalCallbacks,
+ List signalClusters, NetworkControllerImpl networkController) {
+ super("EthernetSignalController", context, NetworkCapabilities.TRANSPORT_ETHERNET,
+ signalCallbacks, signalClusters, networkController);
+ mCurrentState.iconGroup = mLastState.iconGroup = new IconGroup(
+ "Ethernet Icons",
+ EthernetIcons.ETHERNET_ICONS,
+ null,
+ AccessibilityContentDescriptions.ETHERNET_CONNECTION_VALUES,
+ 0, 0, 0, 0,
+ AccessibilityContentDescriptions.ETHERNET_CONNECTION_VALUES[0]);
+ }
+
+ @Override
+ public void notifyListeners() {
+ boolean ethernetVisible = mCurrentState.connected;
+ String contentDescription = getStringIfExists(getContentDescription());
+
+ // TODO: wire up data transfer using WifiSignalPoller.
+ int signalClustersLength = mSignalClusters.size();
+ for (int i = 0; i < signalClustersLength; i++) {
+ mSignalClusters.get(i).setEthernetIndicators(ethernetVisible, getCurrentIconId(),
+ contentDescription);
+ }
+ }
+
+ @Override
+ public SignalController.State cleanState() {
+ return new SignalController.State();
+ }
+
+ public void setConnected(boolean connected) {
+ mCurrentState.connected = connected;
+ notifyListenersIfNecessary();
+ }
+}
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 9adf0285ef11e..6d88535b9aefc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -73,6 +73,10 @@ public class NetworkControllerImpl extends BroadcastReceiver
// Subcontrollers.
@VisibleForTesting
final WifiSignalController mWifiSignalController;
+
+ @VisibleForTesting
+ final EthernetSignalController mEthernetSignalController;
+
@VisibleForTesting
final Map mMobileSignalControllers =
new HashMap();
@@ -154,6 +158,9 @@ public class NetworkControllerImpl extends BroadcastReceiver
mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature,
mSignalsChangedCallbacks, mSignalClusters, this);
+ mEthernetSignalController = new EthernetSignalController(mContext, mSignalsChangedCallbacks,
+ mSignalClusters, this);
+
// AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it
updateAirplaneMode(true /* force callback */);
}
@@ -281,6 +288,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
R.string.accessibility_airplane_mode);
cluster.setNoSims(mHasNoSims);
mWifiSignalController.notifyListeners();
+ mEthernetSignalController.notifyListeners();
for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
mobileSignalController.notifyListeners();
}
@@ -291,6 +299,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
cb.onAirplaneModeChanged(mAirplaneMode);
cb.onNoSimVisibleChanged(mHasNoSims);
mWifiSignalController.notifyListeners();
+ mEthernetSignalController.notifyListeners();
for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
mobileSignalController.notifyListeners();
}
@@ -501,6 +510,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
mobileSignalController.notifyListeners();
}
mWifiSignalController.notifyListeners();
+ mEthernetSignalController.notifyListeners();
}
/**
@@ -560,6 +570,11 @@ public class NetworkControllerImpl extends BroadcastReceiver
}
mWifiSignalController.setInetCondition(
mValidatedTransports.get(mWifiSignalController.getTransportType()) ? 1 : 0);
+
+ mEthernetSignalController.setConnected(
+ mConnectedTransports.get(mEthernetSignalController.getTransportType()));
+ mEthernetSignalController.setInetCondition(
+ mValidatedTransports.get(mEthernetSignalController.getTransportType()) ? 1 : 0);
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -586,6 +601,8 @@ public class NetworkControllerImpl extends BroadcastReceiver
}
mWifiSignalController.dump(pw);
+ mEthernetSignalController.dump(pw);
+
mAccessPoints.dump(pw);
}
@@ -731,6 +748,8 @@ public class NetworkControllerImpl extends BroadcastReceiver
void setSubs(List subs);
void setNoSims(boolean show);
+ void setEthernetIndicators(boolean visible, int icon, String contentDescription);
+
void setIsAirplaneMode(boolean is, int airplaneIcon, int contentDescription);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerEthernetTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerEthernetTest.java
new file mode 100644
index 0000000000000..82ced9f817a3a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerEthernetTest.java
@@ -0,0 +1,40 @@
+package com.android.systemui.statusbar.policy;
+
+import android.net.NetworkCapabilities;
+
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+
+public class NetworkControllerEthernetTest extends NetworkControllerBaseTest {
+
+ public void testEthernetIcons() {
+ verifyLastEthernetIcon(false, 0);
+
+ setEthernetState(true, false); // Connected, unvalidated.
+ verifyLastEthernetIcon(true, EthernetIcons.ETHERNET_ICONS[0][0]);
+
+ setEthernetState(true, true); // Connected, validated.
+ verifyLastEthernetIcon(true, EthernetIcons.ETHERNET_ICONS[1][0]);
+
+ setEthernetState(true, false); // Connected, unvalidated.
+ verifyLastEthernetIcon(true, EthernetIcons.ETHERNET_ICONS[0][0]);
+
+ setEthernetState(false, false); // Disconnected.
+ verifyLastEthernetIcon(false, 0);
+ }
+
+ protected void setEthernetState(boolean connected, boolean validated) {
+ setConnectivity(validated ? 100 : 0, NetworkCapabilities.TRANSPORT_ETHERNET, connected);
+ }
+
+ protected void verifyLastEthernetIcon(boolean visible, int icon) {
+ ArgumentCaptor visibleArg = ArgumentCaptor.forClass(Boolean.class);
+ ArgumentCaptor iconArg = ArgumentCaptor.forClass(Integer.class);
+
+ Mockito.verify(mSignalCluster, Mockito.atLeastOnce()).setEthernetIndicators(
+ visibleArg.capture(), iconArg.capture(),
+ ArgumentCaptor.forClass(String.class).capture());
+ assertEquals("Ethernet visible, in status bar", visible, (boolean) visibleArg.getValue());
+ assertEquals("Ethernet icon, in status bar", icon, (int) iconArg.getValue());
+ }
+}