Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 397b3fe9 authored by Xiao Ma's avatar Xiao Ma Committed by Automerger Merge Worker
Browse files

Merge "Adapt new EthernetManager APIs in Settings." am: 3340b8e3 am: b3fedd06

Original change: https://android-review.googlesource.com/c/platform/packages/apps/Settings/+/1968461

Change-Id: Ifd244bd60e65937c510a5447c9642225be400e3f
parents e6472982 b3fedd06
Loading
Loading
Loading
Loading
+27 −18
Original line number Diff line number Diff line
@@ -34,6 +34,9 @@ import android.content.IntentFilter;
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.Handler;
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 com.android.settingslib.search.SearchIndexable;
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 @@ public class TetherSettings extends RestrictedSettingsFragment
    private BroadcastReceiver mTetherChangeReceiver;

    private String[] mBluetoothRegexs;
    private String mEthernetRegex;
    private AtomicReference<BluetoothPan> mBluetoothPan = new AtomicReference<>();

    private Handler mHandler = new Handler();
@@ -106,6 +109,7 @@ public class TetherSettings extends RestrictedSettingsFragment
    private EthernetManager mEm;
    private TetheringEventCallback mTetheringEventCallback;
    private EthernetListener mEthernetListener;
    private final HashSet<String> mAvailableInterfaces = new HashSet<>();

    private WifiTetherPreferenceController mWifiTetherPreferenceController;

@@ -172,17 +176,17 @@ public class TetherSettings extends RestrictedSettingsFragment
        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 @@ public class TetherSettings extends RestrictedSettingsFragment

        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 @@ public class TetherSettings extends RestrictedSettingsFragment
        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 @@ public class TetherSettings extends RestrictedSettingsFragment
        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 @@ public class TetherSettings extends RestrictedSettingsFragment
        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 @@ public class TetherSettings extends RestrictedSettingsFragment
                        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 @@ public class TetherSettings extends RestrictedSettingsFragment
        }
    }

    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();
        }
    }
}
+31 −12
Original line number Diff line number Diff line
@@ -21,52 +21,63 @@ import android.net.EthernetManager;
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 @@ public final class EthernetTetherPreferenceController extends TetherBasePreferen

    @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());
        }
    }
}
+8 −3
Original line number Diff line number Diff line
@@ -33,8 +33,10 @@ import static org.mockito.Mockito.when;

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.PreferenceGroup;
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.Mock;
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"};
@@ -72,6 +71,8 @@ public class AllInOneTetherSettingsTest {
    private Context mContext;
    private AllInOneTetherSettings mAllInOneTetherSettings;

    @Mock
    private WifiManager mWifiManager;
    @Mock
    private ConnectivityManager mConnectivityManager;
    @Mock
@@ -84,16 +85,20 @@ public class AllInOneTetherSettingsTest {
    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();
+11 −8
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.settings.network;
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 @@ public class EthernetTetherPreferenceControllerTest {
        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 class EthernetTetherPreferenceControllerTest {
    public void lifecycle_shouldRegisterReceiverOnStart() {
        mController.onStart();

        verify(mEthernetManager).addListener(eq(mController.mEthernetListener));
        verify(mEthernetManager).addInterfaceStateListener(any(),
                eq(mController.mEthernetListener));
    }

    @Test
@@ -93,11 +94,10 @@ public class EthernetTetherPreferenceControllerTest {
    @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 @@ public class EthernetTetherPreferenceControllerTest {

    @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