From d46bb58fa635110bf8c911107819e8bd8e8b06e2 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 27 Apr 2015 20:32:01 +0900 Subject: [PATCH] Add a status bar icon for Ethernet. Bug: 20613953 Change-Id: I52970b4f5fb6429876d1a2eb195a834c9e020021 --- .../res/drawable/stat_sys_ethernet.xml | 30 ++++++++ .../res/drawable/stat_sys_ethernet_fully.xml | 24 +++++++ .../res/layout/signal_cluster_view.xml | 19 ++++++ packages/SystemUI/res/values/strings.xml | 5 ++ .../systemui/statusbar/SignalClusterView.java | 46 ++++++++++++- .../AccessibilityContentDescriptions.java | 5 ++ .../statusbar/policy/EthernetIcons.java | 26 +++++++ .../policy/EthernetSignalController.java | 68 +++++++++++++++++++ .../policy/NetworkControllerImpl.java | 19 ++++++ .../policy/NetworkControllerEthernetTest.java | 40 +++++++++++ 10 files changed, 279 insertions(+), 3 deletions(-) create mode 100644 packages/SystemUI/res/drawable/stat_sys_ethernet.xml create mode 100644 packages/SystemUI/res/drawable/stat_sys_ethernet_fully.xml create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetIcons.java create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java create mode 100644 packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerEthernetTest.java 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()); + } +}