From 112a638cbaf478ff3b9260c7bcff6a5a99cc2bc2 Mon Sep 17 00:00:00 2001 From: Hugh Chen Date: Wed, 7 Jul 2021 17:27:12 +0800 Subject: [PATCH] Fix it will auto switch back to "No data transfer" after selecting "USB Tethering" Before this CL, the USB option didn't handle whether FUNCTION_NCM existed in the intent extra when tethering was started which resulted in some devices that enable NCM will have incorrect UI. This CL added a condition to check whether FUNCTION_NCM existed in the intent extra or not to fix this UI issue. Bug: 192046902 Test: make -j42 RunSettingsRoboTests Change-Id: Icb8548409930d59dc3a08c25e418c9a1ddb9f33c --- .../usb/UsbConnectionBroadcastReceiver.java | 3 + .../usb/UsbDefaultFragment.java | 22 +++++-- .../usb/UsbDetailsFunctionsController.java | 4 +- .../UsbConnectionBroadcastReceiverTest.java | 14 +++++ .../usb/UsbDefaultFragmentTest.java | 61 ++++++++++++++++++- .../UsbDetailsFunctionsControllerTest.java | 27 ++++++++ 6 files changed, 122 insertions(+), 9 deletions(-) diff --git a/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiver.java b/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiver.java index a203534dded..c5bcbed00cb 100644 --- a/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiver.java +++ b/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiver.java @@ -75,6 +75,9 @@ public class UsbConnectionBroadcastReceiver extends BroadcastReceiver implements if (intent.getExtras().getBoolean(UsbManager.USB_FUNCTION_ACCESSORY)) { functions |= UsbManager.FUNCTION_ACCESSORY; } + if (intent.getExtras().getBoolean(UsbManager.USB_FUNCTION_NCM)) { + functions |= UsbManager.FUNCTION_NCM; + } mFunctions = functions; mDataRole = mUsbBackend.getDataRole(); mPowerRole = mUsbBackend.getPowerRole(); diff --git a/src/com/android/settings/connecteddevice/usb/UsbDefaultFragment.java b/src/com/android/settings/connecteddevice/usb/UsbDefaultFragment.java index 502c7d25b9c..97906703069 100644 --- a/src/com/android/settings/connecteddevice/usb/UsbDefaultFragment.java +++ b/src/com/android/settings/connecteddevice/usb/UsbDefaultFragment.java @@ -74,8 +74,10 @@ public class UsbDefaultFragment extends RadioButtonPickerFragment { Log.d(TAG, "UsbConnectionListener() connected : " + connected + ", functions : " + functions + ", defaultFunctions : " + defaultFunctions + ", mIsStartTethering : " + mIsStartTethering); - if (connected && !mIsConnected && defaultFunctions == UsbManager.FUNCTION_RNDIS + if (connected && !mIsConnected && (defaultFunctions == UsbManager.FUNCTION_RNDIS + || defaultFunctions == UsbManager.FUNCTION_NCM) && !mIsStartTethering) { + mCurrentFunctions = defaultFunctions; startTethering(); } @@ -150,7 +152,11 @@ public class UsbDefaultFragment extends RadioButtonPickerFragment { @Override protected String getDefaultKey() { - return UsbBackend.usbFunctionsToString(mUsbBackend.getDefaultUsbFunctions()); + long defaultUsbFunctions = mUsbBackend.getDefaultUsbFunctions(); + // Because we didn't have an option for NCM, so make FUNCTION_NCM corresponding to + // FUNCTION_RNDIS for initializing the UI. + return UsbBackend.usbFunctionsToString(defaultUsbFunctions == UsbManager.FUNCTION_NCM + ? UsbManager.FUNCTION_RNDIS : defaultUsbFunctions); } @Override @@ -158,9 +164,10 @@ public class UsbDefaultFragment extends RadioButtonPickerFragment { long functions = UsbBackend.usbFunctionsFromString(key); mPreviousFunctions = mUsbBackend.getCurrentFunctions(); if (!Utils.isMonkeyRunning()) { - if (functions == UsbManager.FUNCTION_RNDIS) { + if (functions == UsbManager.FUNCTION_RNDIS || functions == UsbManager.FUNCTION_NCM) { // We need to have entitlement check for usb tethering, so use API in // TetheringManager. + mCurrentFunctions = functions; startTethering(); } else { mIsStartTethering = false; @@ -193,8 +200,7 @@ public class UsbDefaultFragment extends RadioButtonPickerFragment { public void onTetheringStarted() { Log.d(TAG, "onTetheringStarted()"); // Set default usb functions again to make internal data persistent - mCurrentFunctions = UsbManager.FUNCTION_RNDIS; - mUsbBackend.setDefaultUsbFunctions(UsbManager.FUNCTION_RNDIS); + mUsbBackend.setDefaultUsbFunctions(mCurrentFunctions); } @Override @@ -214,7 +220,11 @@ public class UsbDefaultFragment extends RadioButtonPickerFragment { final boolean isSupported = mUsbBackend.areFunctionsSupported(option); pref.setEnabled(isSupported); if (isSupported) { - pref.setChecked(functions == option); + if (functions == UsbManager.FUNCTION_NCM) { + pref.setChecked(UsbManager.FUNCTION_RNDIS == option); + } else { + pref.setChecked(functions == option); + } } } } diff --git a/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsController.java b/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsController.java index 821bb26f18e..006f72a39ef 100644 --- a/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsController.java +++ b/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsController.java @@ -116,6 +116,8 @@ public class UsbDetailsFunctionsController extends UsbDetailsController if (mUsbBackend.areFunctionsSupported(option)) { if (isAccessoryMode(functions)) { pref.setChecked(UsbManager.FUNCTION_MTP == option); + } else if (functions == UsbManager.FUNCTION_NCM) { + pref.setChecked(UsbManager.FUNCTION_RNDIS == option); } else { pref.setChecked(functions == option); } @@ -148,7 +150,7 @@ public class UsbDetailsFunctionsController extends UsbDetailsController preference.setChecked(true); } - if (function == UsbManager.FUNCTION_RNDIS) { + if (function == UsbManager.FUNCTION_RNDIS || function == UsbManager.FUNCTION_NCM) { // We need to have entitlement check for usb tethering, so use API in // TetheringManager. mTetheringManager.startTethering( diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiverTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiverTest.java index b6bbe8ad6fc..21ec48e0f06 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiverTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiverTest.java @@ -98,6 +98,20 @@ public class UsbConnectionBroadcastReceiverTest { POWER_ROLE_NONE, DATA_ROLE_NONE); } + @Test + public void onReceive_usbConnectedNcmEnabled_invokesCallback() { + Intent intent = new Intent(); + intent.setAction(UsbManager.ACTION_USB_STATE); + intent.putExtra(UsbManager.USB_CONNECTED, true); + intent.putExtra(UsbManager.USB_FUNCTION_NCM, true); + intent.putExtra(UsbManager.USB_DATA_UNLOCKED, true); + + mReceiver.onReceive(mContext, intent); + + verify(mListener).onUsbConnectionChanged(/* connected */ true, UsbManager.FUNCTION_NCM, + POWER_ROLE_NONE, DATA_ROLE_NONE); + } + @Test public void onReceive_usbPortStatus_invokeCallback() { final Intent intent = new Intent(); diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDefaultFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDefaultFragmentTest.java index f3e1bcedc7b..eee63980753 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDefaultFragmentTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDefaultFragmentTest.java @@ -103,6 +103,14 @@ public class UsbDefaultFragmentTest { .isEqualTo(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_MIDI)); } + @Test + public void getDefaultKey_isNcm_returnsRndis() { + when(mUsbBackend.getDefaultUsbFunctions()).thenReturn(UsbManager.FUNCTION_NCM); + + assertThat(mFragment.getDefaultKey()) + .isEqualTo(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_RNDIS)); + } + @Test public void setDefaultKey_isNone_shouldSetNone() { mFragment.setDefaultKey(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_NONE)); @@ -149,6 +157,19 @@ public class UsbDefaultFragmentTest { UsbManager.FUNCTION_MTP); } + @Test + public void setDefaultKey_functionNcm_invokesStartTethering() { + doReturn(UsbManager.FUNCTION_MTP).when(mUsbBackend).getCurrentFunctions(); + + mFragment.setDefaultKey(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_NCM)); + + verify(mTetheringManager).startTethering(eq(TetheringManager.TETHERING_USB), + any(), + eq(mFragment.mOnStartTetheringCallback)); + assertThat(mFragment.mPreviousFunctions).isEqualTo( + UsbManager.FUNCTION_MTP); + } + @Test public void setDefaultKey_functionOther_setCurrentFunctionInvoked() { doReturn(UsbManager.FUNCTION_MTP).when(mUsbBackend).getCurrentFunctions(); @@ -161,14 +182,24 @@ public class UsbDefaultFragmentTest { } @Test - public void onTetheringStarted_setDefaultUsbFunctions() { - mFragment.mPreviousFunctions = UsbManager.FUNCTION_PTP; + public void onTetheringStarted_currentFunctionsIsRndis_setsRndisAsDefaultUsbFunctions() { + mFragment.mCurrentFunctions = UsbManager.FUNCTION_RNDIS; mFragment.mOnStartTetheringCallback.onTetheringStarted(); verify(mUsbBackend).setDefaultUsbFunctions(UsbManager.FUNCTION_RNDIS); } + @Test + public void onTetheringStarted_currentFunctionsIsNcm_setsNcmAsDefaultUsbFunctions() { + mFragment.mCurrentFunctions = UsbManager.FUNCTION_NCM; + + mFragment.mOnStartTetheringCallback.onTetheringStarted(); + + verify(mUsbBackend).setDefaultUsbFunctions(UsbManager.FUNCTION_NCM); + } + + @Test public void onPause_receivedRndis_shouldSetRndis() { mFragment.mIsStartTethering = true; @@ -229,6 +260,18 @@ public class UsbDefaultFragmentTest { assertThat(mFragment.mCurrentFunctions).isEqualTo(UsbManager.FUNCTION_MIDI); } + @Test + public void onPause_receivedNcm_setsNcm() { + mFragment.mIsStartTethering = true; + mFragment.mUsbConnectionListener.onUsbConnectionChanged(/* connected */ true, + UsbManager.FUNCTION_NCM, POWER_ROLE_SINK, DATA_ROLE_DEVICE); + + mFragment.onPause(); + + verify(mUsbBackend, times(2)).setDefaultUsbFunctions(UsbManager.FUNCTION_NCM); + assertThat(mFragment.mCurrentFunctions).isEqualTo(UsbManager.FUNCTION_NCM); + } + @Test public void usbIsPluginAndUsbTetheringIsOn_startTetheringIsInvoked() { when(mUsbBackend.getDefaultUsbFunctions()).thenReturn(UsbManager.FUNCTION_RNDIS); @@ -243,6 +286,20 @@ public class UsbDefaultFragmentTest { eq(mFragment.mOnStartTetheringCallback)); } + @Test + public void usbIsPluginAndUsbTetheringIsOn_receivedNcm_startsTethering() { + when(mUsbBackend.getDefaultUsbFunctions()).thenReturn(UsbManager.FUNCTION_NCM); + + mFragment.mUsbConnectionListener.onUsbConnectionChanged(/* connected */ false, + UsbManager.FUNCTION_NCM, POWER_ROLE_SINK, DATA_ROLE_DEVICE); + mFragment.mUsbConnectionListener.onUsbConnectionChanged(/* connected */ true, + UsbManager.FUNCTION_NCM, POWER_ROLE_SINK, DATA_ROLE_DEVICE); + + verify(mTetheringManager).startTethering(eq(TetheringManager.TETHERING_USB), + any(), + eq(mFragment.mOnStartTetheringCallback)); + } + @Test public void usbIsNotPluginAndUsbTetheringIsOn_startTetheringIsNotInvoked() { when(mUsbBackend.getDefaultUsbFunctions()).thenReturn(UsbManager.FUNCTION_RNDIS); diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsControllerTest.java index 9118645ce61..f94ab6a5d96 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsControllerTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsControllerTest.java @@ -167,6 +167,19 @@ public class UsbDetailsFunctionsControllerTest { assertThat(prefs.get(0).isChecked()).isTrue(); } + @Test + public void displayRefresh_ncmEnabled_checksSwitches() { + when(mUsbBackend.areFunctionsSupported(anyLong())).thenReturn(true); + + mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_NCM, POWER_ROLE_SINK, + DATA_ROLE_DEVICE); + List prefs = getRadioPreferences(); + + assertThat(prefs.get(1).getKey()) + .isEqualTo(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_RNDIS)); + assertThat(prefs.get(1).isChecked()).isTrue(); + } + @Test public void onClickMtp_noneEnabled_shouldEnableMtp() { when(mUsbBackend.areFunctionsSupported(anyLong())).thenReturn(true); @@ -253,6 +266,20 @@ public class UsbDetailsFunctionsControllerTest { UsbManager.FUNCTION_MTP); } + @Test + public void onRadioButtonClicked_functionNcm_startsTethering() { + mRadioButtonPreference.setKey(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_NCM)); + doReturn(UsbManager.FUNCTION_MTP).when(mUsbBackend).getCurrentFunctions(); + + mDetailsFunctionsController.onRadioButtonClicked(mRadioButtonPreference); + + verify(mTetheringManager).startTethering(eq(TetheringManager.TETHERING_USB), + any(), + eq(mDetailsFunctionsController.mOnStartTetheringCallback)); + assertThat(mDetailsFunctionsController.mPreviousFunction).isEqualTo( + UsbManager.FUNCTION_MTP); + } + @Test public void onRadioButtonClicked_functionOther_setCurrentFunctionInvoked() { mRadioButtonPreference.setKey(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_PTP));