Prevent unnecessary reconnection for wifi privacy

Before fix, privacy toggle in the Network details page causes a
disconnection + reconnection even when selecting the same setting.

Check current setting first to prevent unnecessary reconnection.

Fix: 303093138
Test: manual - select same privacy setting
Test: unit test
Change-Id: I71208e3cd256fdc0dd5e895fa1a68fdab47aed9a
diff --git a/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java
index 76fed9b..8c78e80 100644
--- a/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java
@@ -72,6 +72,10 @@
     @Override
     public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) {
         final int privacy = Integer.parseInt((String) newValue);
+        if (mWifiEntry.getPrivacy() == privacy) {
+            // Prevent disconnection + reconnection if settings not changed.
+            return true;
+        }
         mWifiEntry.setPrivacy(privacy);
 
         // To activate changing, we need to reconnect network. WiFi will auto connect to
diff --git a/tests/robotests/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.java b/tests/robotests/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.java
deleted file mode 100644
index d3244fa..0000000
--- a/tests/robotests/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.wifi.details2;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-
-import androidx.preference.DropDownPreference;
-
-import com.android.settings.R;
-import com.android.wifitrackerlib.WifiEntry;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class WifiPrivacyPreferenceController2Test {
-
-    private static final int PRIVACY_RANDOMIZED = WifiEntry.PRIVACY_RANDOMIZED_MAC;
-    private static final int PRIVACY_TRUSTED = WifiEntry.PRIVACY_DEVICE_MAC;
-
-    @Mock private WifiEntry mMockWifiEntry;
-
-    private WifiPrivacyPreferenceController2 mPreferenceController;
-    private Context mContext;
-    private DropDownPreference mDropDownPreference;
-    private String[] mPerferenceStrings;
-
-    @Before
-    public void setUp() {
-        mContext = RuntimeEnvironment.application;
-
-        mMockWifiEntry = mock(WifiEntry.class);
-        WifiPrivacyPreferenceController2 preferenceController =
-                new WifiPrivacyPreferenceController2(mContext);
-        preferenceController.setWifiEntry(mMockWifiEntry);
-        mPreferenceController = spy(preferenceController);
-        mDropDownPreference = new DropDownPreference(mContext);
-        mDropDownPreference.setEntries(R.array.wifi_privacy_entries);
-        mDropDownPreference.setEntryValues(R.array.wifi_privacy_values);
-
-        mPerferenceStrings = mContext.getResources().getStringArray(R.array.wifi_privacy_entries);
-    }
-
-    @Test
-    public void testUpdateState_wifiPrivacy_setCorrectValue() {
-        doReturn(PRIVACY_TRUSTED).when(mPreferenceController).getRandomizationValue();
-
-        mPreferenceController.updateState(mDropDownPreference);
-
-        int prefValue = mPreferenceController.translateMacRandomizedValueToPrefValue(
-                PRIVACY_TRUSTED);
-        assertThat(mDropDownPreference.getEntry()).isEqualTo(mPerferenceStrings[prefValue]);
-    }
-
-    @Test
-    public void testUpdateState_wifiNotMetered_setCorrectValue() {
-        doReturn(PRIVACY_RANDOMIZED).when(mPreferenceController).getRandomizationValue();
-
-        mPreferenceController.updateState(mDropDownPreference);
-
-        int prefValue = mPreferenceController.translateMacRandomizedValueToPrefValue(
-                PRIVACY_RANDOMIZED);
-        assertThat(mDropDownPreference.getEntry()).isEqualTo(mPerferenceStrings[prefValue]);
-    }
-
-    @Test
-    public void testUpdateState_canSetPrivacyInNextUpdate_shouldBeSelectable() {
-        // Return false in WifiEntry#canSetPrivacy to make preference un-selectable first.
-        when(mMockWifiEntry.canSetPrivacy()).thenReturn(false);
-
-        mPreferenceController.updateState(mDropDownPreference);
-
-        assertThat(mDropDownPreference.isSelectable()).isFalse();
-
-        // Return true in WifiEntry#canSetPrivacy to verify preference back to selectable.
-        when(mMockWifiEntry.canSetPrivacy()).thenReturn(true);
-
-        mPreferenceController.updateState(mDropDownPreference);
-
-        assertThat(mDropDownPreference.isSelectable()).isTrue();
-    }
-
-    @Test
-    public void testUpdateState_canNotSetPrivacyInNextUpdate_shouldNotBeSelectable() {
-        // Return true in WifiEntry#canSetPrivacy to make preference selectable first.
-        when(mMockWifiEntry.canSetPrivacy()).thenReturn(true);
-
-        mPreferenceController.updateState(mDropDownPreference);
-
-        assertThat(mDropDownPreference.isSelectable()).isTrue();
-
-        // Return false in WifiEntry#canSetPrivacy to verify preference back to un-selectable.
-        when(mMockWifiEntry.canSetPrivacy()).thenReturn(false);
-
-        mPreferenceController.updateState(mDropDownPreference);
-
-        assertThat(mDropDownPreference.isSelectable()).isFalse();
-    }
-}
diff --git a/tests/spa_unit/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.kt b/tests/spa_unit/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.kt
new file mode 100644
index 0000000..cb1f997
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.kt
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi.details2
+
+import android.content.Context
+import androidx.preference.ListPreference
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.R
+import com.android.wifitrackerlib.WifiEntry
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.never
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.stub
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+
+@RunWith(AndroidJUnit4::class)
+class WifiPrivacyPreferenceController2Test {
+    private var mockWifiEntry = mock<WifiEntry>()
+
+    private var context: Context = ApplicationProvider.getApplicationContext()
+
+    private var controller = spy(WifiPrivacyPreferenceController2(context).apply {
+        setWifiEntry(mockWifiEntry)
+    })
+
+    private var preference = ListPreference(context).apply {
+        setEntries(R.array.wifi_privacy_entries)
+        setEntryValues(R.array.wifi_privacy_values)
+    }
+
+    private var preferenceStrings = context.resources.getStringArray(R.array.wifi_privacy_entries)
+
+    @Test
+    fun updateState_wifiPrivacy_setCorrectValue() {
+        controller.stub {
+            doReturn(WifiEntry.PRIVACY_DEVICE_MAC).whenever(mock).randomizationValue
+        }
+
+        controller.updateState(preference)
+
+        val prefValue = WifiPrivacyPreferenceController2.translateMacRandomizedValueToPrefValue(
+            WifiEntry.PRIVACY_DEVICE_MAC
+        )
+        assertThat(preference.entry).isEqualTo(preferenceStrings[prefValue])
+    }
+
+    @Test
+    fun updateState_wifiNotMetered_setCorrectValue() {
+        controller.stub {
+            doReturn(WifiEntry.PRIVACY_RANDOMIZED_MAC).whenever(mock).randomizationValue
+        }
+
+        controller.updateState(preference)
+
+        val prefValue = WifiPrivacyPreferenceController2.translateMacRandomizedValueToPrefValue(
+            WifiEntry.PRIVACY_RANDOMIZED_MAC
+        )
+        assertThat(preference.entry).isEqualTo(preferenceStrings[prefValue])
+    }
+
+    @Test
+    fun updateState_canSetPrivacyInNextUpdate_shouldBeSelectable() {
+        mockWifiEntry.stub {
+            // Return false in WifiEntry#canSetPrivacy to make preference un-selectable first.
+            on { canSetPrivacy() } doReturn false
+        }
+        controller.updateState(preference)
+        assertThat(preference.isSelectable).isFalse()
+
+        mockWifiEntry.stub {
+            // Return true in WifiEntry#canSetPrivacy to verify preference back to selectable.
+            on { canSetPrivacy() } doReturn true
+        }
+        controller.updateState(preference)
+        assertThat(preference.isSelectable).isTrue()
+    }
+
+    @Test
+    fun updateState_canNotSetPrivacyInNextUpdate_shouldNotBeSelectable() {
+        mockWifiEntry.stub {
+            // Return true in WifiEntry#canSetPrivacy to make preference selectable first.
+            on { canSetPrivacy() } doReturn true
+        }
+        controller.updateState(preference)
+        assertThat(preference.isSelectable).isTrue()
+
+        mockWifiEntry.stub {
+            // Return false in WifiEntry#canSetPrivacy to verify preference back to un-selectable.
+            on { canSetPrivacy() } doReturn false
+        }
+        controller.updateState(preference)
+        assertThat(preference.isSelectable).isFalse()
+    }
+
+    @Test
+    fun onPreferenceChange_sameNewValue_doNoting() {
+        mockWifiEntry.stub {
+            on { privacy } doReturn 0
+            on { connectedState } doReturn WifiEntry.CONNECTED_STATE_CONNECTED
+        }
+
+        controller.onPreferenceChange(preference, "0")
+
+        verify(mockWifiEntry, never()).privacy = any()
+        verify(mockWifiEntry, never()).disconnect(null)
+        verify(mockWifiEntry, never()).connect(null)
+    }
+
+    @Test
+    fun onPreferenceChange_differentNewValue_setAndReconnect() {
+        mockWifiEntry.stub {
+            on { privacy } doReturn 0
+            on { connectedState } doReturn WifiEntry.CONNECTED_STATE_CONNECTED
+        }
+
+        controller.onPreferenceChange(preference, "1")
+
+        verify(mockWifiEntry).privacy = 1
+        verify(mockWifiEntry).disconnect(null)
+        verify(mockWifiEntry).connect(null)
+    }
+}