Merge "Remove `Use on-screen keyboard` preference from Physical Keyboard page" into main
diff --git a/aconfig/settings_connecteddevice_flag_declarations.aconfig b/aconfig/settings_connecteddevice_flag_declarations.aconfig
index 693e398..b255096 100644
--- a/aconfig/settings_connecteddevice_flag_declarations.aconfig
+++ b/aconfig/settings_connecteddevice_flag_declarations.aconfig
@@ -38,3 +38,13 @@
         purpose: PURPOSE_BUGFIX
     }
 }
+
+flag {
+    name: "exclude_webcam_auth_challenge"
+    namespace: "safety_center"
+    description: "Gates whether to exclude webcam from USB preferences auth challenge."
+    bug: "349370229"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
\ No newline at end of file
diff --git a/res/layout/request_manage_credentials.xml b/res/layout/request_manage_credentials.xml
index 4f6a5c4..c25a35d 100644
--- a/res/layout/request_manage_credentials.xml
+++ b/res/layout/request_manage_credentials.xml
@@ -18,7 +18,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content"
+    android:layout_height="match_parent"
     android:fitsSystemWindows="true"
     android:clipChildren="true">
 
diff --git a/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsController.java b/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsController.java
index 04fab7d..ae9dbeb 100644
--- a/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsController.java
+++ b/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsController.java
@@ -31,6 +31,7 @@
 
 import com.android.settings.R;
 import com.android.settings.Utils;
+import com.android.settings.flags.Flags;
 import com.android.settingslib.widget.SelectorWithWidgetPreference;
 
 import java.util.LinkedHashMap;
@@ -130,39 +131,54 @@
 
     @Override
     public void onRadioButtonClicked(SelectorWithWidgetPreference preference) {
-        requireAuthAndExecute(() -> {
-            final long function = UsbBackend.usbFunctionsFromString(preference.getKey());
-            final long previousFunction = mUsbBackend.getCurrentFunctions();
-            if (DEBUG) {
-                Log.d(TAG, "onRadioButtonClicked() function : " + function + ", toString() : "
-                        + UsbManager.usbFunctionsToString(function) + ", previousFunction : "
-                        + previousFunction + ", toString() : "
-                        + UsbManager.usbFunctionsToString(previousFunction));
-            }
-            if (function != previousFunction && !Utils.isMonkeyRunning()
-                    && !isClickEventIgnored(function, previousFunction)) {
-                mPreviousFunction = previousFunction;
+        final long function = UsbBackend.usbFunctionsFromString(preference.getKey());
+        if (isAuthRequired(function)) {
+            requireAuthAndExecute(()->handleRadioButtonClicked(preference, function));
+        } else {
+            handleRadioButtonClicked(preference, function);
+        }
+    }
 
-                //Update the UI in advance to make it looks smooth
-                final SelectorWithWidgetPreference prevPref =
-                        (SelectorWithWidgetPreference) mProfilesContainer.findPreference(
-                                UsbBackend.usbFunctionsToString(mPreviousFunction));
-                if (prevPref != null) {
-                    prevPref.setChecked(false);
-                    preference.setChecked(true);
-                }
+    private void handleRadioButtonClicked(SelectorWithWidgetPreference preference, long function) {
+        final long previousFunction = mUsbBackend.getCurrentFunctions();
+        if (DEBUG) {
+            Log.d(TAG, "onRadioButtonClicked() function : " + function + ", toString() : "
+                    + UsbManager.usbFunctionsToString(function) + ", previousFunction : "
+                    + previousFunction + ", toString() : "
+                    + UsbManager.usbFunctionsToString(previousFunction));
+        }
+        if (function != previousFunction && !Utils.isMonkeyRunning()
+                && !isClickEventIgnored(function, previousFunction)) {
+            mPreviousFunction = previousFunction;
 
-                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(
-                            TetheringManager.TETHERING_USB, new HandlerExecutor(mHandler),
-                            mOnStartTetheringCallback);
-                } else {
-                    mUsbBackend.setCurrentFunctions(function);
-                }
+            //Update the UI in advance to make it looks smooth
+            final SelectorWithWidgetPreference prevPref =
+                    (SelectorWithWidgetPreference) mProfilesContainer.findPreference(
+                            UsbBackend.usbFunctionsToString(mPreviousFunction));
+            if (prevPref != null) {
+                prevPref.setChecked(false);
+                preference.setChecked(true);
             }
-        });
+
+            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(
+                        TetheringManager.TETHERING_USB, new HandlerExecutor(mHandler),
+                        mOnStartTetheringCallback);
+            } else {
+                mUsbBackend.setCurrentFunctions(function);
+            }
+        }
+    }
+
+    private boolean isAuthRequired(long function) {
+        if (!Flags.excludeWebcamAuthChallenge()) {
+            return true;
+        }
+        // Since webcam and MIDI don't transfer any persistent data over USB
+        // don't require authentication.
+        return !(function == UsbManager.FUNCTION_UVC || function == UsbManager.FUNCTION_MIDI);
     }
 
     private boolean isClickEventIgnored(long function, long previousFunction) {
diff --git a/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceController.kt b/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceController.kt
index 1e635a5..621465e 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceController.kt
+++ b/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceController.kt
@@ -91,7 +91,6 @@
             )
             return
         }
-        preference.isVisible = false
 
         val viewModel by lazyViewModel
         coroutineScope = viewLifecycleOwner.lifecycleScope
@@ -127,7 +126,6 @@
         preference.title = title
         preference.dialogTitle = title
         preference.summary = eid
-        preference.isVisible = eid.isNotEmpty()
     }
 
     override fun handlePreferenceTreeClick(preference: Preference): Boolean {
diff --git a/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceController.kt b/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceController.kt
index a6fb7ba..6b3f903 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceController.kt
+++ b/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceController.kt
@@ -113,7 +113,6 @@
     private fun refreshUi(){
         preference.title = title
         preference.summary = imei
-        preference.isVisible = true
     }
 
     override fun handlePreferenceTreeClick(preference: Preference): Boolean {
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 eea4f52..9427bbe 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsControllerTest.java
@@ -35,6 +35,8 @@
 import android.hardware.usb.UsbManager;
 import android.net.TetheringManager;
 import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 
 import androidx.fragment.app.FragmentActivity;
 import androidx.preference.PreferenceCategory;
@@ -48,6 +50,7 @@
 
 import org.junit.Before;
 import org.junit.Ignore;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -82,6 +85,8 @@
     private FragmentActivity mActivity;
     @Mock
     private TetheringManager mTetheringManager;
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
 
     @Before
     public void setUp() {
@@ -349,6 +354,30 @@
         assertThat(mFragment.isUserAuthenticated()).isTrue();
     }
 
+    @Test
+    @RequiresFlagsEnabled(Flags.FLAG_EXCLUDE_WEBCAM_AUTH_CHALLENGE)
+    public void onRadioButtonClicked_webcamNoAuthNeeded() {
+        mRadioButtonPreference.setKey(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_UVC));
+        doReturn(UsbManager.FUNCTION_MTP).when(mUsbBackend).getCurrentFunctions();
+        setAuthPassesAutomatically();
+
+        mDetailsFunctionsController.onRadioButtonClicked(mRadioButtonPreference);
+
+        assertThat(mFragment.isUserAuthenticated()).isFalse();
+    }
+
+    @Test
+    @RequiresFlagsEnabled(Flags.FLAG_EXCLUDE_WEBCAM_AUTH_CHALLENGE)
+    public void onRadioButtonClicked_MidiNoAuthNeeded() {
+        mRadioButtonPreference.setKey(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_MIDI));
+        doReturn(UsbManager.FUNCTION_MTP).when(mUsbBackend).getCurrentFunctions();
+        setAuthPassesAutomatically();
+
+        mDetailsFunctionsController.onRadioButtonClicked(mRadioButtonPreference);
+
+        assertThat(mFragment.isUserAuthenticated()).isFalse();
+    }
+
     private void setAuthPassesAutomatically() {
         Shadows.shadowOf(mContext.getSystemService(KeyguardManager.class))
                 .setIsKeyguardSecure(false);