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

Commit d6ec2ac7 authored by hughchen's avatar hughchen
Browse files

Tethering shouldn't indicates on when SIM without tethering option

Before this CL, If SIM doesn't have tethering option then UI will not
back to previous option when press "USB tethering" in
[Default USB configuration].

This CL added receiver to observe USB state that get correct state
from UsbManager.

Bug: 138630479
Test: make -j42 RunSettingsRoboTests
Change-Id: I6cc8da508f6ab142142ca8c28460125bad93925b
parent 08d00412
Loading
Loading
Loading
Loading
+17 −19
Original line number Diff line number Diff line
@@ -57,7 +57,6 @@ public class UsbConnectionBroadcastReceiver extends BroadcastReceiver implements
        if (UsbManager.ACTION_USB_STATE.equals(intent.getAction())) {
            mConnected = intent.getExtras().getBoolean(UsbManager.USB_CONNECTED)
                    || intent.getExtras().getBoolean(UsbManager.USB_HOST_CONNECTED);
            if (mConnected) {
            long functions = UsbManager.FUNCTION_NONE;
            if (intent.getExtras().getBoolean(UsbManager.USB_FUNCTION_MTP)
                    && intent.getExtras().getBoolean(UsbManager.USB_DATA_UNLOCKED, false)) {
@@ -76,7 +75,6 @@ public class UsbConnectionBroadcastReceiver extends BroadcastReceiver implements
            mFunctions = functions;
            mDataRole = mUsbBackend.getDataRole();
            mPowerRole = mUsbBackend.getPowerRole();
            }
        } else if (UsbManager.ACTION_USB_PORT_CHANGED.equals(intent.getAction())) {
            UsbPortStatus portStatus = intent.getExtras()
                    .getParcelable(UsbManager.EXTRA_PORT_STATUS);
+46 −0
Original line number Diff line number Diff line
@@ -26,12 +26,14 @@ import android.net.ConnectivityManager;
import android.os.Bundle;

import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceScreen;

import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.widget.RadioButtonPickerFragment;
import com.android.settingslib.widget.CandidateInfo;
import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.RadioButtonPreference;

import com.google.android.collect.Lists;

@@ -49,12 +51,31 @@ public class UsbDefaultFragment extends RadioButtonPickerFragment {
    OnStartTetheringCallback mOnStartTetheringCallback = new OnStartTetheringCallback();
    @VisibleForTesting
    long mPreviousFunctions;
    @VisibleForTesting
    long mCurrentFunctions;
    @VisibleForTesting
    boolean mIsStartTethering = false;

    private UsbConnectionBroadcastReceiver mUsbReceiver;

    @VisibleForTesting
    UsbConnectionBroadcastReceiver.UsbConnectionListener mUsbConnectionListener =
            (connected, functions, powerRole, dataRole) -> {
                if (mIsStartTethering) {
                    mCurrentFunctions = functions;
                    refresh(functions);
                }
            };

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mUsbBackend = new UsbBackend(context);
        mConnectivityManager = context.getSystemService(ConnectivityManager.class);
        mUsbReceiver = new UsbConnectionBroadcastReceiver(context, mUsbConnectionListener,
                mUsbBackend);
        getSettingsLifecycle().addObserver(mUsbReceiver);
        mCurrentFunctions = mUsbBackend.getDefaultUsbFunctions();
    }

    @Override
@@ -118,9 +139,12 @@ public class UsbDefaultFragment extends RadioButtonPickerFragment {
            if (functions == UsbManager.FUNCTION_RNDIS) {
                // We need to have entitlement check for usb tethering, so use API in
                // ConnectivityManager.
                mIsStartTethering = true;
                mConnectivityManager.startTethering(TETHERING_USB, true /* showProvisioningUi */,
                        mOnStartTetheringCallback);
            } else {
                mIsStartTethering = false;
                mCurrentFunctions = functions;
                mUsbBackend.setDefaultUsbFunctions(functions);
            }

@@ -128,6 +152,12 @@ public class UsbDefaultFragment extends RadioButtonPickerFragment {
        return true;
    }

    @Override
    public void onPause() {
        super.onPause();
        mUsbBackend.setDefaultUsbFunctions(mCurrentFunctions);
    }

    @VisibleForTesting
    final class OnStartTetheringCallback extends
            ConnectivityManager.OnStartTetheringCallback {
@@ -136,6 +166,7 @@ public class UsbDefaultFragment extends RadioButtonPickerFragment {
        public void onTetheringStarted() {
            super.onTetheringStarted();
            // Set default usb functions again to make internal data persistent
            mCurrentFunctions = UsbManager.FUNCTION_RNDIS;
            mUsbBackend.setDefaultUsbFunctions(UsbManager.FUNCTION_RNDIS);
        }

@@ -146,4 +177,19 @@ public class UsbDefaultFragment extends RadioButtonPickerFragment {
            updateCandidates();
        }
    }

    private void refresh(long functions) {
        final PreferenceScreen screen = getPreferenceScreen();
        for (long option : UsbDetailsFunctionsController.FUNCTIONS_MAP.keySet()) {
            final RadioButtonPreference pref =
                    screen.findPreference(UsbBackend.usbFunctionsToString(option));
            if (pref != null) {
                final boolean isSupported = mUsbBackend.areFunctionsSupported(option);
                pref.setEnabled(isSupported);
                if (isSupported) {
                    pref.setChecked(functions == option);
                }
            }
        }
    }
}
 No newline at end of file
+79 −1
Original line number Diff line number Diff line
@@ -16,12 +16,15 @@

package com.android.settings.connecteddevice.usb;

import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
import static android.net.ConnectivityManager.TETHERING_USB;

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

import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -29,6 +32,8 @@ import static org.mockito.Mockito.when;
import android.hardware.usb.UsbManager;
import android.net.ConnectivityManager;

import androidx.preference.PreferenceScreen;

import com.android.settings.testutils.shadow.ShadowUtils;

import org.junit.Before;
@@ -52,7 +57,7 @@ public class UsbDefaultFragmentTest {
    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mFragment = new UsbDefaultFragment();
        mFragment = new TestFragment();
        mFragment.mUsbBackend = mUsbBackend;
        mFragment.mConnectivityManager = mConnectivityManager;
    }
@@ -156,4 +161,77 @@ public class UsbDefaultFragmentTest {

        verify(mUsbBackend).setDefaultUsbFunctions(UsbManager.FUNCTION_RNDIS);
    }

    @Test
    public void onPause_receivedRndis_shouldSetRndis() {
        mFragment.mIsStartTethering = true;
        mFragment.mUsbConnectionListener.onUsbConnectionChanged(true /* connected */,
                UsbManager.FUNCTION_RNDIS, POWER_ROLE_SINK, DATA_ROLE_DEVICE);

        mFragment.onPause();

        verify(mUsbBackend).setDefaultUsbFunctions(UsbManager.FUNCTION_RNDIS);
        assertThat(mFragment.mCurrentFunctions).isEqualTo(UsbManager.FUNCTION_RNDIS);
    }

    @Test
    public void onPause_receivedNone_shouldSetNone() {
        mFragment.mIsStartTethering = true;
        mFragment.mUsbConnectionListener.onUsbConnectionChanged(true /* connected */,
                UsbManager.FUNCTION_NONE, POWER_ROLE_SINK, DATA_ROLE_DEVICE);

        mFragment.onPause();

        verify(mUsbBackend).setDefaultUsbFunctions(UsbManager.FUNCTION_NONE);
        assertThat(mFragment.mCurrentFunctions).isEqualTo(UsbManager.FUNCTION_NONE);
    }

    @Test
    public void onPause_receivedMtp_shouldSetMtp() {
        mFragment.mIsStartTethering = true;
        mFragment.mUsbConnectionListener.onUsbConnectionChanged(true /* connected */,
                UsbManager.FUNCTION_MTP, POWER_ROLE_SINK, DATA_ROLE_DEVICE);

        mFragment.onPause();

        verify(mUsbBackend).setDefaultUsbFunctions(UsbManager.FUNCTION_MTP);
        assertThat(mFragment.mCurrentFunctions).isEqualTo(UsbManager.FUNCTION_MTP);
    }

    @Test
    public void onPause_receivedPtp_shouldSetPtp() {
        mFragment.mIsStartTethering = true;
        mFragment.mUsbConnectionListener.onUsbConnectionChanged(true /* connected */,
                UsbManager.FUNCTION_PTP, POWER_ROLE_SINK, DATA_ROLE_DEVICE);

        mFragment.onPause();

        verify(mUsbBackend).setDefaultUsbFunctions(UsbManager.FUNCTION_PTP);
        assertThat(mFragment.mCurrentFunctions).isEqualTo(UsbManager.FUNCTION_PTP);
    }

    @Test
    public void onPause_receivedMidi_shouldSetMidi() {
        mFragment.mIsStartTethering = true;
        mFragment.mUsbConnectionListener.onUsbConnectionChanged(true /* connected */,
                UsbManager.FUNCTION_MIDI, POWER_ROLE_SINK, DATA_ROLE_DEVICE);

        mFragment.onPause();

        verify(mUsbBackend).setDefaultUsbFunctions(UsbManager.FUNCTION_MIDI);
        assertThat(mFragment.mCurrentFunctions).isEqualTo(UsbManager.FUNCTION_MIDI);
    }

    public static class TestFragment extends UsbDefaultFragment {
        public final PreferenceScreen mScreen;

        public TestFragment() {
            mScreen = mock(PreferenceScreen.class);
        }

        @Override
        public PreferenceScreen getPreferenceScreen() {
            return mScreen;
        }
    }
}