Merge "Adapt new EthernetManager APIs in Settings." am: 3340b8e3c3 am: b3fedd0633
Original change: https://android-review.googlesource.com/c/platform/packages/apps/Settings/+/1968461
Change-Id: Ifd244bd60e65937c510a5447c9642225be400e3f
diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java
index e485d1e..ae24168 100644
--- a/src/com/android/settings/TetherSettings.java
+++ b/src/com/android/settings/TetherSettings.java
@@ -34,6 +34,9 @@
import android.hardware.usb.UsbManager;
import android.net.ConnectivityManager;
import android.net.EthernetManager;
+import android.net.EthernetManager.InterfaceState;
+import android.net.EthernetManager.Role;
+import android.net.IpConfiguration;
import android.net.TetheringManager;
import android.net.wifi.WifiManager;
import android.os.Bundle;
@@ -42,10 +45,10 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.SearchIndexableResource;
-import android.text.TextUtils;
import android.util.FeatureFlagUtils;
import android.util.Log;
+import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.SwitchPreference;
@@ -62,6 +65,7 @@
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
@@ -97,7 +101,6 @@
private BroadcastReceiver mTetherChangeReceiver;
private String[] mBluetoothRegexs;
- private String mEthernetRegex;
private AtomicReference<BluetoothPan> mBluetoothPan = new AtomicReference<>();
private Handler mHandler = new Handler();
@@ -106,6 +109,7 @@
private EthernetManager mEm;
private TetheringEventCallback mTetheringEventCallback;
private EthernetListener mEthernetListener;
+ private final HashSet<String> mAvailableInterfaces = new HashSet<>();
private WifiTetherPreferenceController mWifiTetherPreferenceController;
@@ -172,17 +176,17 @@
mDataSaverBackend.addListener(this);
mCm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
- mEm = (EthernetManager) getSystemService(Context.ETHERNET_SERVICE);
mTm = (TetheringManager) getSystemService(Context.TETHERING_SERVICE);
+ // Some devices do not have available EthernetManager. In that case getSystemService will
+ // return null.
+ mEm = mContext.getSystemService(EthernetManager.class);
mUsbRegexs = mTm.getTetherableUsbRegexs();
mBluetoothRegexs = mTm.getTetherableBluetoothRegexs();
- mEthernetRegex = mContext.getResources().getString(
- com.android.internal.R.string.config_ethernet_iface_regex);
final boolean usbAvailable = mUsbRegexs.length != 0;
final boolean bluetoothAvailable = adapter != null && mBluetoothRegexs.length != 0;
- final boolean ethernetAvailable = !TextUtils.isEmpty(mEthernetRegex);
+ final boolean ethernetAvailable = (mEm != null);
if (!usbAvailable || Utils.isMonkeyRunning()) {
getPreferenceScreen().removePreference(mUsbTether);
@@ -330,7 +334,7 @@
mEthernetListener = new EthernetListener();
if (mEm != null)
- mEm.addListener(mEthernetListener, r -> mHandler.post(r));
+ mEm.addInterfaceStateListener(r -> mHandler.post(r), mEthernetListener);
updateUsbState();
updateBluetoothAndEthernetState();
@@ -346,11 +350,10 @@
getActivity().unregisterReceiver(mTetherChangeReceiver);
mTm.unregisterTetheringEventCallback(mTetheringEventCallback);
if (mEm != null)
- mEm.removeListener(mEthernetListener);
+ mEm.removeInterfaceStateListener(mEthernetListener);
mTetherChangeReceiver = null;
mStartTetheringCallback = null;
mTetheringEventCallback = null;
- mEthernetListener = null;
}
@VisibleForTesting
@@ -483,11 +486,11 @@
boolean isTethered = false;
for (String s : available) {
- if (s.matches(mEthernetRegex)) isAvailable = true;
+ if (mAvailableInterfaces.contains(s)) isAvailable = true;
}
for (String s : tethered) {
- if (s.matches(mEthernetRegex)) isTethered = true;
+ if (mAvailableInterfaces.contains(s)) isTethered = true;
}
if (DEBUG) {
@@ -498,7 +501,7 @@
if (isTethered) {
mEthernetTether.setEnabled(!mDataSaverEnabled);
mEthernetTether.setChecked(true);
- } else if (isAvailable || (mEm != null && mEm.isAvailable())) {
+ } else if (mAvailableInterfaces.size() > 0) {
mEthernetTether.setEnabled(!mDataSaverEnabled);
mEthernetTether.setChecked(false);
} else {
@@ -600,9 +603,9 @@
keys.add(KEY_ENABLE_BLUETOOTH_TETHERING);
}
- final boolean ethernetAvailable = !TextUtils.isEmpty(
- context.getResources().getString(
- com.android.internal.R.string.config_ethernet_iface_regex));
+ final EthernetManager em =
+ context.getSystemService(EthernetManager.class);
+ final boolean ethernetAvailable = (em != null);
if (!ethernetAvailable) {
keys.add(KEY_ENABLE_ETHERNET_TETHERING);
}
@@ -646,9 +649,15 @@
}
}
- private final class EthernetListener implements EthernetManager.Listener {
- public void onAvailabilityChanged(String iface, boolean isAvailable) {
- mHandler.post(() -> updateBluetoothAndEthernetState());
+ private final class EthernetListener implements EthernetManager.InterfaceStateListener {
+ public void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state,
+ @Role int role, @NonNull IpConfiguration configuration) {
+ if (state == EthernetManager.STATE_LINK_UP) {
+ mAvailableInterfaces.add(iface);
+ } else {
+ mAvailableInterfaces.remove(iface);
+ }
+ updateBluetoothAndEthernetState();
}
}
}
diff --git a/src/com/android/settings/network/EthernetTetherPreferenceController.java b/src/com/android/settings/network/EthernetTetherPreferenceController.java
index 5b2cab7..58c1fd2 100644
--- a/src/com/android/settings/network/EthernetTetherPreferenceController.java
+++ b/src/com/android/settings/network/EthernetTetherPreferenceController.java
@@ -21,52 +21,63 @@
import android.net.TetheringManager;
import android.os.Handler;
import android.os.Looper;
-import android.text.TextUtils;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.OnLifecycleEvent;
import com.android.internal.annotations.VisibleForTesting;
+import java.util.HashSet;
+
/**
* This controller helps to manage the switch state and visibility of ethernet tether switch
* preference.
*/
public final class EthernetTetherPreferenceController extends TetherBasePreferenceController {
- private final String mEthernetRegex;
+ private final HashSet<String> mAvailableInterfaces = new HashSet<>();
private final EthernetManager mEthernetManager;
+
@VisibleForTesting
- EthernetManager.Listener mEthernetListener;
+ EthernetManager.InterfaceStateListener mEthernetListener;
public EthernetTetherPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
- mEthernetRegex = context.getString(
- com.android.internal.R.string.config_ethernet_iface_regex);
- mEthernetManager = (EthernetManager) context.getSystemService(Context.ETHERNET_SERVICE);
+ mEthernetManager = context.getSystemService(EthernetManager.class);
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onStart() {
- mEthernetListener = (iface, isAvailable) -> updateState(mPreference);
+ mEthernetListener = (iface, state, role, configuration) -> {
+ if (state == EthernetManager.STATE_LINK_UP) {
+ mAvailableInterfaces.add(iface);
+ } else {
+ mAvailableInterfaces.remove(iface);
+ }
+ updateState(mPreference);
+ };
final Handler handler = new Handler(Looper.getMainLooper());
// Executor will execute to post the updateState event to a new handler which is created
// from the main looper when the {@link EthernetManager.Listener.onAvailabilityChanged}
// is triggerd.
- mEthernetManager.addListener(mEthernetListener, r -> handler.post(r));
+ if (mEthernetManager != null) {
+ mEthernetManager.addInterfaceStateListener(r -> handler.post(r), mEthernetListener);
+ }
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onStop() {
- mEthernetManager.removeListener(mEthernetListener);
- mEthernetListener = null;
+ if (mEthernetManager != null) {
+ mEthernetManager.removeInterfaceStateListener(mEthernetListener);
+ }
}
@Override
public boolean shouldEnable() {
+ ensureRunningOnMainLoopThread();
String[] available = mTm.getTetherableIfaces();
for (String s : available) {
- if (s.matches(mEthernetRegex)) {
+ if (mAvailableInterfaces.contains(s)) {
return true;
}
}
@@ -75,11 +86,19 @@
@Override
public boolean shouldShow() {
- return !TextUtils.isEmpty(mEthernetRegex);
+ return mEthernetManager != null;
}
@Override
public int getTetherType() {
return TetheringManager.TETHERING_ETHERNET;
}
+
+ private void ensureRunningOnMainLoopThread() {
+ if (Looper.getMainLooper().getThread() != Thread.currentThread()) {
+ throw new IllegalStateException(
+ "Not running on main loop thread: "
+ + Thread.currentThread().getName());
+ }
+ }
}
diff --git a/tests/robotests/src/com/android/settings/AllInOneTetherSettingsTest.java b/tests/robotests/src/com/android/settings/AllInOneTetherSettingsTest.java
index cd33663..01ec42e 100644
--- a/tests/robotests/src/com/android/settings/AllInOneTetherSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/AllInOneTetherSettingsTest.java
@@ -33,8 +33,10 @@
import android.content.Context;
import android.net.ConnectivityManager;
+import android.net.EthernetManager;
import android.net.TetheringManager;
import android.net.wifi.SoftApConfiguration;
+import android.net.wifi.WifiManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.FeatureFlagUtils;
@@ -43,7 +45,6 @@
import androidx.preference.PreferenceScreen;
import com.android.settings.core.FeatureFlags;
-import com.android.settings.testutils.shadow.ShadowWifiManager;
import com.android.settings.wifi.tether.WifiTetherAutoOffPreferenceController;
import com.android.settings.wifi.tether.WifiTetherSecurityPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -55,14 +56,12 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
-@Config(shadows = {ShadowWifiManager.class})
public class AllInOneTetherSettingsTest {
private static final String[] WIFI_REGEXS = {"wifi_regexs"};
private static final String[] USB_REGEXS = {"usb_regexs"};
@@ -73,6 +72,8 @@
private AllInOneTetherSettings mAllInOneTetherSettings;
@Mock
+ private WifiManager mWifiManager;
+ @Mock
private ConnectivityManager mConnectivityManager;
@Mock
private TetheringManager mTetheringManager;
@@ -84,16 +85,20 @@
private PreferenceScreen mPreferenceScreen;
@Mock
private PreferenceGroup mWifiTetherGroup;
+ @Mock
+ private EthernetManager mEthernetManager;
@Before
public void setUp() {
mContext = spy(RuntimeEnvironment.application);
MockitoAnnotations.initMocks(this);
+ doReturn(mWifiManager).when(mContext).getSystemService(WifiManager.class);
doReturn(mConnectivityManager)
.when(mContext).getSystemService(Context.CONNECTIVITY_SERVICE);
doReturn(mTetheringManager)
.when(mContext).getSystemService(Context.TETHERING_SERVICE);
+ doReturn(mEthernetManager).when(mContext).getSystemService(EthernetManager.class);
doReturn(WIFI_REGEXS).when(mTetheringManager).getTetherableWifiRegexs();
doReturn(USB_REGEXS).when(mTetheringManager).getTetherableUsbRegexs();
doReturn(BT_REGEXS).when(mTetheringManager).getTetherableBluetoothRegexs();
diff --git a/tests/robotests/src/com/android/settings/network/EthernetTetherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/EthernetTetherPreferenceControllerTest.java
index 8a81908..df82a67 100644
--- a/tests/robotests/src/com/android/settings/network/EthernetTetherPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/EthernetTetherPreferenceControllerTest.java
@@ -19,6 +19,7 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -64,10 +65,9 @@
mPreference = spy(SwitchPreference.class);
when(mContext.getSystemService(Context.TETHERING_SERVICE)).thenReturn(mTetheringManager);
when(mTetheringManager.getTetherableIfaces()).thenReturn(new String[]{ETHERNET_REGEX});
- when(mContext.getSystemService(Context.ETHERNET_SERVICE)).thenReturn(mEthernetManager);
+ when(mContext.getSystemService(EthernetManager.class)).thenReturn(mEthernetManager);
mController = new EthernetTetherPreferenceController(mContext, "ethernet");
mController.setTetherEnabler(mTetherEnabler);
- ReflectionHelpers.setField(mController, "mEthernetRegex", ETHERNET_REGEX);
ReflectionHelpers.setField(mController, "mPreference", mPreference);
}
@@ -75,7 +75,8 @@
public void lifecycle_shouldRegisterReceiverOnStart() {
mController.onStart();
- verify(mEthernetManager).addListener(eq(mController.mEthernetListener));
+ verify(mEthernetManager).addInterfaceStateListener(any(),
+ eq(mController.mEthernetListener));
}
@Test
@@ -93,11 +94,10 @@
@Test
public void lifecycle_shouldUnregisterReceiverOnStop() {
mController.onStart();
- EthernetManager.Listener listener = mController.mEthernetListener;
+ EthernetManager.InterfaceStateListener listener = mController.mEthernetListener;
mController.onStop();
- verify(mEthernetManager).removeListener(eq(listener));
- assertThat(mController.mEthernetListener).isNull();
+ verify(mEthernetManager).removeInterfaceStateListener(eq(listener));
}
@Test
@@ -108,8 +108,11 @@
@Test
public void shouldShow_noEthernetInterface() {
- ReflectionHelpers.setField(mController, "mEthernetRegex", "");
- assertThat(mController.shouldShow()).isFalse();
+ when(mContext.getSystemService(EthernetManager.class)).thenReturn(null);
+
+ final EthernetTetherPreferenceController controller =
+ new EthernetTetherPreferenceController(mContext, "ethernet");
+ assertThat(controller.shouldShow()).isFalse();
}
@Test