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

Commit 3876d72b authored by Ted Wang's avatar Ted Wang
Browse files

Update state when there is Bluetooth tethering state changed

Monitor Bluetooth Tethering state and update preference when there is
Bluetooth tethering state change.
Add test case to verify when recieve
BluetoothPan.TETHERING_STATE_CHANGED will update bluetooth state

Bug: 138688805
Test: make RunSettingsRoboTests
Merged-Id: I8f468d1d99ed6d87f6cd8305ef56b0d7a5dec95b
Change-Id: I8f468d1d99ed6d87f6cd8305ef56b0d7a5dec95b
parent 94d3a30b
Loading
Loading
Loading
Loading
+68 −33
Original line number Diff line number Diff line
@@ -80,6 +80,10 @@ public class TetherSettings extends RestrictedSettingsFragment
    @VisibleForTesting
    static final String KEY_TETHER_PREFS_FOOTER = "tether_prefs_footer";

    @VisibleForTesting
    static final String BLUETOOTH_TETHERING_STATE_CHANGED =
            "android.bluetooth.pan.profile.action.TETHERING_STATE_CHANGED";

    private static final String TAG = "TetheringSettings";

    private SwitchPreference mUsbTether;
@@ -154,9 +158,7 @@ public class TetherSettings extends RestrictedSettingsFragment
                    BluetoothProfile.PAN);
        }

        mUsbTether = (SwitchPreference) findPreference(KEY_USB_TETHER_SETTINGS);
        mBluetoothTether = (SwitchPreference) findPreference(KEY_ENABLE_BLUETOOTH_TETHERING);
        mEthernetTether = (SwitchPreference) findPreference(KEY_ENABLE_ETHERNET_TETHERING);
        setupTetherPreference();
        setFooterPreferenceTitle();

        mDataSaverBackend.addListener(this);
@@ -208,6 +210,13 @@ public class TetherSettings extends RestrictedSettingsFragment
        super.onDestroy();
    }

    @VisibleForTesting
    void setupTetherPreference() {
        mUsbTether = (SwitchPreference) findPreference(KEY_USB_TETHER_SETTINGS);
        mBluetoothTether = (SwitchPreference) findPreference(KEY_ENABLE_BLUETOOTH_TETHERING);
        mEthernetTether = (SwitchPreference) findPreference(KEY_ENABLE_ETHERNET_TETHERING);
    }

    @Override
    public void onDataSaverChanged(boolean isDataSaving) {
        mDataSaverEnabled = isDataSaving;
@@ -281,6 +290,8 @@ public class TetherSettings extends RestrictedSettingsFragment
                    }
                }
                updateState();
            } else if (action.equals(BLUETOOTH_TETHERING_STATE_CHANGED)) {
                updateState();
            }
        }
    }
@@ -297,32 +308,13 @@ public class TetherSettings extends RestrictedSettingsFragment
            return;
        }

        final Activity activity = getActivity();

        mStartTetheringCallback = new OnStartTetheringCallback(this);
        mTetheringEventCallback = new TetheringEventCallback();
        mTm.registerTetheringEventCallback(new HandlerExecutor(mHandler), mTetheringEventCallback);

        mMassStorageActive = Environment.MEDIA_SHARED.equals(Environment.getExternalStorageState());
        mTetherChangeReceiver = new TetherChangeReceiver();
        IntentFilter filter = new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
        Intent intent = activity.registerReceiver(mTetherChangeReceiver, filter);

        filter = new IntentFilter();
        filter.addAction(UsbManager.ACTION_USB_STATE);
        activity.registerReceiver(mTetherChangeReceiver, filter);

        filter = new IntentFilter();
        filter.addAction(Intent.ACTION_MEDIA_SHARED);
        filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
        filter.addDataScheme("file");
        activity.registerReceiver(mTetherChangeReceiver, filter);

        filter = new IntentFilter();
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        activity.registerReceiver(mTetherChangeReceiver, filter);

        if (intent != null) mTetherChangeReceiver.onReceive(activity, intent);
        registerReceiver();

        mEthernetListener = new EthernetListener();
        if (mEm != null)
@@ -348,10 +340,38 @@ public class TetherSettings extends RestrictedSettingsFragment
        mEthernetListener = null;
    }

    @VisibleForTesting
    void registerReceiver() {
        final Activity activity = getActivity();

        mTetherChangeReceiver = new TetherChangeReceiver();
        IntentFilter filter = new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
        final Intent intent = activity.registerReceiver(mTetherChangeReceiver, filter);

        filter = new IntentFilter();
        filter.addAction(UsbManager.ACTION_USB_STATE);
        activity.registerReceiver(mTetherChangeReceiver, filter);

        filter = new IntentFilter();
        filter.addAction(Intent.ACTION_MEDIA_SHARED);
        filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
        filter.addDataScheme("file");
        activity.registerReceiver(mTetherChangeReceiver, filter);

        filter = new IntentFilter();
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        filter.addAction(BLUETOOTH_TETHERING_STATE_CHANGED);
        activity.registerReceiver(mTetherChangeReceiver, filter);

        if (intent != null) mTetherChangeReceiver.onReceive(activity, intent);
    }

    private void updateState() {
        String[] available = mCm.getTetherableIfaces();
        String[] tethered = mCm.getTetheredIfaces();
        String[] errored = mCm.getTetheringErroredIfaces();
        final ConnectivityManager cm =
                (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        final String[] available = cm.getTetherableIfaces();
        final String[] tethered = cm.getTetheredIfaces();
        final String[] errored = cm.getTetheringErroredIfaces();
        updateState(available, tethered, errored);
    }

@@ -362,7 +382,8 @@ public class TetherSettings extends RestrictedSettingsFragment
        updateEthernetState(available, tethered);
    }

    private void updateUsbState(String[] available, String[] tethered,
    @VisibleForTesting
    void updateUsbState(String[] available, String[] tethered,
            String[] errored) {
        boolean usbAvailable = mUsbConnected && !mMassStorageActive;
        int usbError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
@@ -400,20 +421,33 @@ public class TetherSettings extends RestrictedSettingsFragment
        }
    }

    private void updateBluetoothState() {
    @VisibleForTesting
    int getBluetoothState() {
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        if (adapter == null) {
            return BluetoothAdapter.ERROR;
        }
        return adapter.getState();
    }

    @VisibleForTesting
    boolean isBluetoothTetheringOn() {
        final BluetoothPan bluetoothPan = mBluetoothPan.get();
        return bluetoothPan != null && bluetoothPan.isTetheringOn();
    }

    private void updateBluetoothState() {
        final int btState = getBluetoothState();
        if (btState == BluetoothAdapter.ERROR) {
            return;
        }
        int btState = adapter.getState();

        if (btState == BluetoothAdapter.STATE_TURNING_OFF) {
            mBluetoothTether.setEnabled(false);
        } else if (btState == BluetoothAdapter.STATE_TURNING_ON) {
            mBluetoothTether.setEnabled(false);
        } else {
            BluetoothPan bluetoothPan = mBluetoothPan.get();
            if (btState == BluetoothAdapter.STATE_ON && bluetoothPan != null
                    && bluetoothPan.isTetheringOn()) {
            if (btState == BluetoothAdapter.STATE_ON && isBluetoothTetheringOn()) {
                mBluetoothTether.setChecked(true);
                mBluetoothTether.setEnabled(!mDataSaverEnabled);
            } else {
@@ -423,7 +457,8 @@ public class TetherSettings extends RestrictedSettingsFragment
        }
    }

    private void updateEthernetState(String[] available, String[] tethered) {
    @VisibleForTesting
    void updateEthernetState(String[] available, String[] tethered) {

        boolean isAvailable = false;
        boolean isTethered = false;
+83 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.settings;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -25,20 +27,27 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.FeatureFlagUtils;

import androidx.fragment.app.FragmentActivity;
import androidx.preference.Preference;
import androidx.preference.SwitchPreference;

import com.android.settings.core.FeatureFlags;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
@@ -160,6 +169,80 @@ public class TetherSettingsTest {
        verify(mockPreference).setTitle(R.string.tethering_footer_info_sta_ap_concurrency);
    }

    @Test
    public void testBluetoothState_updateBluetoothState_bluetoothTetheringStateOn() {
        final TetherSettings spyTetherSettings = spy(new TetherSettings());
        when(spyTetherSettings.getContext()).thenReturn(mContext);
        final SwitchPreference mockSwitchPreference = mock(SwitchPreference.class);
        when(spyTetherSettings.findPreference(TetherSettings.KEY_ENABLE_BLUETOOTH_TETHERING))
            .thenReturn(mockSwitchPreference);
        final FragmentActivity mockActivity = mock(FragmentActivity.class);
        when(spyTetherSettings.getActivity()).thenReturn(mockActivity);
        final ArgumentCaptor<BroadcastReceiver> captor =
                ArgumentCaptor.forClass(BroadcastReceiver.class);
        when(mockActivity.registerReceiver(captor.capture(), any(IntentFilter.class)))
            .thenReturn(null);
        // Bluetooth tethering state is on
        when(spyTetherSettings.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON);
        when(spyTetherSettings.isBluetoothTetheringOn()).thenReturn(true);

        spyTetherSettings.setupTetherPreference();
        spyTetherSettings.registerReceiver();
        updateOnlyBluetoothState(spyTetherSettings);

        // Simulate Bluetooth tethering state changed
        final BroadcastReceiver receiver = captor.getValue();
        final Intent bluetoothTetheringChanged =
                new Intent(TetherSettings.BLUETOOTH_TETHERING_STATE_CHANGED);
        receiver.onReceive(mockActivity, bluetoothTetheringChanged);

        verify(mockSwitchPreference).setEnabled(true);
        verify(mockSwitchPreference).setChecked(true);
    }

    @Test
    public void testBluetoothState_updateBluetoothState_bluetoothTetheringStateOff() {
        final TetherSettings spyTetherSettings = spy(new TetherSettings());
        when(spyTetherSettings.getContext()).thenReturn(mContext);
        final SwitchPreference mockSwitchPreference = mock(SwitchPreference.class);
        when(spyTetherSettings.findPreference(TetherSettings.KEY_ENABLE_BLUETOOTH_TETHERING))
            .thenReturn(mockSwitchPreference);
        final FragmentActivity mockActivity = mock(FragmentActivity.class);
        when(spyTetherSettings.getActivity()).thenReturn(mockActivity);
        final ArgumentCaptor<BroadcastReceiver> captor =
                ArgumentCaptor.forClass(BroadcastReceiver.class);
        when(mockActivity.registerReceiver(captor.capture(), any(IntentFilter.class)))
            .thenReturn(null);
        // Bluetooth tethering state is off
        when(spyTetherSettings.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON);
        when(spyTetherSettings.isBluetoothTetheringOn()).thenReturn(false);

        spyTetherSettings.setupTetherPreference();
        spyTetherSettings.registerReceiver();
        updateOnlyBluetoothState(spyTetherSettings);

        // Simulate Bluetooth tethering state changed
        final BroadcastReceiver receiver = captor.getValue();
        final Intent bluetoothTetheringChanged =
                new Intent(TetherSettings.BLUETOOTH_TETHERING_STATE_CHANGED);
        receiver.onReceive(mockActivity, bluetoothTetheringChanged);

        verify(mockSwitchPreference).setEnabled(true);
        verify(mockSwitchPreference).setChecked(false);
    }

    private void updateOnlyBluetoothState(TetherSettings tetherSettings) {
        doReturn(mConnectivityManager).when(tetherSettings)
            .getSystemService(Context.CONNECTIVITY_SERVICE);
        when(mConnectivityManager.getTetherableIfaces()).thenReturn(new String[0]);
        when(mConnectivityManager.getTetheredIfaces()).thenReturn(new String[0]);
        when(mConnectivityManager.getTetheringErroredIfaces()).thenReturn(new String[0]);
        doNothing().when(tetherSettings).updateUsbState(any(String[].class), any(String[].class),
                any(String[].class));
        doNothing().when(tetherSettings).updateEthernetState(any(String[].class),
                any(String[].class));
    }

    private void setupIsTetherAvailable(boolean returnValue) {
        when(mConnectivityManager.isTetheringSupported()).thenReturn(true);