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
This commit is contained in:
hughchen
2019-07-31 06:14:54 +08:00
parent 08d0041259
commit d6ec2ac7be
3 changed files with 142 additions and 20 deletions

View File

@@ -57,7 +57,6 @@ public class UsbConnectionBroadcastReceiver extends BroadcastReceiver implements
if (UsbManager.ACTION_USB_STATE.equals(intent.getAction())) { if (UsbManager.ACTION_USB_STATE.equals(intent.getAction())) {
mConnected = intent.getExtras().getBoolean(UsbManager.USB_CONNECTED) mConnected = intent.getExtras().getBoolean(UsbManager.USB_CONNECTED)
|| intent.getExtras().getBoolean(UsbManager.USB_HOST_CONNECTED); || intent.getExtras().getBoolean(UsbManager.USB_HOST_CONNECTED);
if (mConnected) {
long functions = UsbManager.FUNCTION_NONE; long functions = UsbManager.FUNCTION_NONE;
if (intent.getExtras().getBoolean(UsbManager.USB_FUNCTION_MTP) if (intent.getExtras().getBoolean(UsbManager.USB_FUNCTION_MTP)
&& intent.getExtras().getBoolean(UsbManager.USB_DATA_UNLOCKED, false)) { && intent.getExtras().getBoolean(UsbManager.USB_DATA_UNLOCKED, false)) {
@@ -76,7 +75,6 @@ public class UsbConnectionBroadcastReceiver extends BroadcastReceiver implements
mFunctions = functions; mFunctions = functions;
mDataRole = mUsbBackend.getDataRole(); mDataRole = mUsbBackend.getDataRole();
mPowerRole = mUsbBackend.getPowerRole(); mPowerRole = mUsbBackend.getPowerRole();
}
} else if (UsbManager.ACTION_USB_PORT_CHANGED.equals(intent.getAction())) { } else if (UsbManager.ACTION_USB_PORT_CHANGED.equals(intent.getAction())) {
UsbPortStatus portStatus = intent.getExtras() UsbPortStatus portStatus = intent.getExtras()
.getParcelable(UsbManager.EXTRA_PORT_STATUS); .getParcelable(UsbManager.EXTRA_PORT_STATUS);

View File

@@ -26,12 +26,14 @@ import android.net.ConnectivityManager;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceScreen;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.widget.RadioButtonPickerFragment; import com.android.settings.widget.RadioButtonPickerFragment;
import com.android.settingslib.widget.CandidateInfo; import com.android.settingslib.widget.CandidateInfo;
import com.android.settingslib.widget.FooterPreference; import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.RadioButtonPreference;
import com.google.android.collect.Lists; import com.google.android.collect.Lists;
@@ -49,12 +51,31 @@ public class UsbDefaultFragment extends RadioButtonPickerFragment {
OnStartTetheringCallback mOnStartTetheringCallback = new OnStartTetheringCallback(); OnStartTetheringCallback mOnStartTetheringCallback = new OnStartTetheringCallback();
@VisibleForTesting @VisibleForTesting
long mPreviousFunctions; 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 @Override
public void onAttach(Context context) { public void onAttach(Context context) {
super.onAttach(context); super.onAttach(context);
mUsbBackend = new UsbBackend(context); mUsbBackend = new UsbBackend(context);
mConnectivityManager = context.getSystemService(ConnectivityManager.class); mConnectivityManager = context.getSystemService(ConnectivityManager.class);
mUsbReceiver = new UsbConnectionBroadcastReceiver(context, mUsbConnectionListener,
mUsbBackend);
getSettingsLifecycle().addObserver(mUsbReceiver);
mCurrentFunctions = mUsbBackend.getDefaultUsbFunctions();
} }
@Override @Override
@@ -118,9 +139,12 @@ public class UsbDefaultFragment extends RadioButtonPickerFragment {
if (functions == UsbManager.FUNCTION_RNDIS) { if (functions == UsbManager.FUNCTION_RNDIS) {
// We need to have entitlement check for usb tethering, so use API in // We need to have entitlement check for usb tethering, so use API in
// ConnectivityManager. // ConnectivityManager.
mIsStartTethering = true;
mConnectivityManager.startTethering(TETHERING_USB, true /* showProvisioningUi */, mConnectivityManager.startTethering(TETHERING_USB, true /* showProvisioningUi */,
mOnStartTetheringCallback); mOnStartTetheringCallback);
} else { } else {
mIsStartTethering = false;
mCurrentFunctions = functions;
mUsbBackend.setDefaultUsbFunctions(functions); mUsbBackend.setDefaultUsbFunctions(functions);
} }
@@ -128,6 +152,12 @@ public class UsbDefaultFragment extends RadioButtonPickerFragment {
return true; return true;
} }
@Override
public void onPause() {
super.onPause();
mUsbBackend.setDefaultUsbFunctions(mCurrentFunctions);
}
@VisibleForTesting @VisibleForTesting
final class OnStartTetheringCallback extends final class OnStartTetheringCallback extends
ConnectivityManager.OnStartTetheringCallback { ConnectivityManager.OnStartTetheringCallback {
@@ -136,6 +166,7 @@ public class UsbDefaultFragment extends RadioButtonPickerFragment {
public void onTetheringStarted() { public void onTetheringStarted() {
super.onTetheringStarted(); super.onTetheringStarted();
// Set default usb functions again to make internal data persistent // Set default usb functions again to make internal data persistent
mCurrentFunctions = UsbManager.FUNCTION_RNDIS;
mUsbBackend.setDefaultUsbFunctions(UsbManager.FUNCTION_RNDIS); mUsbBackend.setDefaultUsbFunctions(UsbManager.FUNCTION_RNDIS);
} }
@@ -146,4 +177,19 @@ public class UsbDefaultFragment extends RadioButtonPickerFragment {
updateCandidates(); 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);
}
}
}
}
} }

View File

@@ -16,12 +16,15 @@
package com.android.settings.connecteddevice.usb; 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 android.net.ConnectivityManager.TETHERING_USB;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -29,6 +32,8 @@ import static org.mockito.Mockito.when;
import android.hardware.usb.UsbManager; import android.hardware.usb.UsbManager;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import androidx.preference.PreferenceScreen;
import com.android.settings.testutils.shadow.ShadowUtils; import com.android.settings.testutils.shadow.ShadowUtils;
import org.junit.Before; import org.junit.Before;
@@ -52,7 +57,7 @@ public class UsbDefaultFragmentTest {
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mFragment = new UsbDefaultFragment(); mFragment = new TestFragment();
mFragment.mUsbBackend = mUsbBackend; mFragment.mUsbBackend = mUsbBackend;
mFragment.mConnectivityManager = mConnectivityManager; mFragment.mConnectivityManager = mConnectivityManager;
} }
@@ -156,4 +161,77 @@ public class UsbDefaultFragmentTest {
verify(mUsbBackend).setDefaultUsbFunctions(UsbManager.FUNCTION_RNDIS); 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;
}
}
} }