Merge "[Catalyst] Migrate Wi-Fi switch preference" into main
This commit is contained in:
committed by
Android (Google) Code Review
commit
0496fc2de5
@@ -53,6 +53,7 @@
|
||||
android:key="main_toggle_wifi"
|
||||
android:title="@string/wifi"
|
||||
settings:keywords="@string/keywords_wifi"
|
||||
settings:restrictedSwitchSummary="@string/not_allowed_by_ent"
|
||||
settings:allowDividerAbove="true"/>
|
||||
|
||||
<PreferenceCategory
|
||||
|
@@ -20,6 +20,7 @@ import android.os.UserManager
|
||||
import com.android.settings.PreferenceRestrictionMixin
|
||||
import com.android.settings.R
|
||||
import com.android.settings.flags.Flags
|
||||
import com.android.settings.wifi.WifiSwitchPreference
|
||||
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
|
||||
import com.android.settingslib.metadata.ProvidePreferenceScreen
|
||||
import com.android.settingslib.metadata.preferenceHierarchy
|
||||
@@ -54,7 +55,9 @@ class NetworkProviderScreen :
|
||||
|
||||
override fun fragmentClass() = NetworkProviderSettings::class.java
|
||||
|
||||
override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {}
|
||||
override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {
|
||||
+WifiSwitchPreference()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val KEY = "internet_settings"
|
||||
|
@@ -429,6 +429,10 @@ public class NetworkProviderSettings extends RestrictedDashboardFragment
|
||||
}
|
||||
|
||||
private void addWifiSwitchPreferenceController() {
|
||||
if (isCatalystEnabled()) {
|
||||
Log.i(TAG, "WifiSwitchPreferenceController bypassed since Catalyst is enabled!");
|
||||
return;
|
||||
}
|
||||
if (!hasWifiManager()) return;
|
||||
if (mWifiSwitchPreferenceController == null) {
|
||||
mWifiSwitchPreferenceController =
|
||||
|
@@ -38,6 +38,7 @@ import com.google.common.annotations.VisibleForTesting;
|
||||
/**
|
||||
* This controller helps to manage the state of wifi switch preference.
|
||||
*/
|
||||
// LINT.IfChange
|
||||
public class WifiSwitchPreferenceController extends AbstractPreferenceController implements
|
||||
LifecycleObserver {
|
||||
|
||||
@@ -125,3 +126,4 @@ public class WifiSwitchPreferenceController extends AbstractPreferenceController
|
||||
return wifiManager.isWifiEnabled();
|
||||
}
|
||||
}
|
||||
// LINT.ThenChange(WifiSwitchPreference.kt)
|
||||
|
144
src/com/android/settings/wifi/WifiSwitchPreference.kt
Normal file
144
src/com/android/settings/wifi/WifiSwitchPreference.kt
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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
|
||||
|
||||
import android.content.Context
|
||||
import android.net.wifi.WifiManager
|
||||
import android.os.UserManager
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import androidx.preference.Preference
|
||||
import com.android.settings.PreferenceRestrictionMixin
|
||||
import com.android.settings.R
|
||||
import com.android.settings.network.SatelliteRepository
|
||||
import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
|
||||
import com.android.settings.widget.GenericSwitchController
|
||||
import com.android.settingslib.RestrictedSwitchPreference
|
||||
import com.android.settingslib.WirelessUtils
|
||||
import com.android.settingslib.datastore.KeyValueStore
|
||||
import com.android.settingslib.datastore.NoOpKeyedObservable
|
||||
import com.android.settingslib.metadata.*
|
||||
import com.android.settingslib.preference.SwitchPreferenceBinding
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
// LINT.IfChange
|
||||
class WifiSwitchPreference :
|
||||
SwitchPreference(KEY, R.string.wifi),
|
||||
SwitchPreferenceBinding,
|
||||
PreferenceLifecycleProvider,
|
||||
PreferenceRestrictionMixin {
|
||||
|
||||
// TODO(b/372733639) Remove WifiEnabler and migrate to catalyst
|
||||
private var wifiEnabler: WifiEnabler? = null
|
||||
|
||||
override val keywords: Int
|
||||
get() = R.string.keywords_wifi
|
||||
|
||||
override fun isEnabled(context: Context) = super<PreferenceRestrictionMixin>.isEnabled(context)
|
||||
|
||||
override val restrictionKeys
|
||||
get() = arrayOf(UserManager.DISALLOW_CHANGE_WIFI_STATE)
|
||||
|
||||
override val useAdminDisabledSummary: Boolean
|
||||
get() = true
|
||||
|
||||
override fun getReadPermit(context: Context, myUid: Int, callingUid: Int) =
|
||||
ReadWritePermit.ALLOW
|
||||
|
||||
override fun getWritePermit(context: Context, value: Boolean?, myUid: Int, callingUid: Int) =
|
||||
when {
|
||||
isRadioAllowed(context, value) && !isSatelliteOn(context) -> ReadWritePermit.ALLOW
|
||||
else -> ReadWritePermit.DISALLOW
|
||||
}
|
||||
|
||||
override fun storage(context: Context): KeyValueStore = WifiSwitchStore(context)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private class WifiSwitchStore(private val context: Context) :
|
||||
NoOpKeyedObservable<String>(),
|
||||
KeyValueStore {
|
||||
|
||||
override fun contains(key: String) =
|
||||
key == KEY && context.getSystemService(WifiManager::class.java) != null
|
||||
|
||||
override fun <T : Any> getValue(key: String, valueType: Class<T>): T? =
|
||||
context.getSystemService(WifiManager::class.java)?.isWifiEnabled as T?
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
|
||||
if (value is Boolean) {
|
||||
context.getSystemService(WifiManager::class.java)?.isWifiEnabled = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(context: PreferenceLifecycleContext) {
|
||||
context.requirePreference<RestrictedSwitchPreference>(KEY).let {
|
||||
it.onPreferenceChangeListener =
|
||||
Preference.OnPreferenceChangeListener { _: Preference, newValue: Any ->
|
||||
if (!isRadioAllowed(context, newValue as Boolean?)) {
|
||||
Log.w(TAG, "Don't set APM, AIRPLANE_MODE_RADIOS is not allowed")
|
||||
return@OnPreferenceChangeListener false
|
||||
}
|
||||
if (isSatelliteOn(context)) {
|
||||
Log.w(TAG, "Don't set APM, the satellite is on")
|
||||
return@OnPreferenceChangeListener false
|
||||
}
|
||||
return@OnPreferenceChangeListener true
|
||||
}
|
||||
val widget = GenericSwitchController(it)
|
||||
wifiEnabler = WifiEnabler(context, widget, featureFactory.metricsFeatureProvider)
|
||||
Log.i(TAG, "Create WifiEnabler:$wifiEnabler")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume(context: PreferenceLifecycleContext) {
|
||||
wifiEnabler?.resume(context)
|
||||
}
|
||||
|
||||
override fun onPause(context: PreferenceLifecycleContext) {
|
||||
wifiEnabler?.pause()
|
||||
}
|
||||
|
||||
override fun onDestroy(context: PreferenceLifecycleContext) {
|
||||
wifiEnabler?.teardownSwitchController()
|
||||
wifiEnabler = null
|
||||
}
|
||||
|
||||
private fun isRadioAllowed(context: Context, newValue: Boolean?): Boolean {
|
||||
newValue?.let { if (!it) return true } ?: return false
|
||||
return WirelessUtils.isRadioAllowed(context, Settings.Global.RADIO_WIFI)
|
||||
}
|
||||
|
||||
private fun isSatelliteOn(context: Context): Boolean {
|
||||
try {
|
||||
return SatelliteRepository(context)
|
||||
.requestIsSessionStarted(Executors.newSingleThreadExecutor())
|
||||
.get(2000, TimeUnit.MILLISECONDS)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Error to get satellite status : $e")
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "WifiSwitchPreference"
|
||||
const val KEY = "main_toggle_wifi"
|
||||
}
|
||||
}
|
||||
// LINT.ThenChange(WifiSwitchPreferenceController.java)
|
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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
|
||||
|
||||
import android.content.ContextWrapper
|
||||
import android.net.wifi.WifiManager
|
||||
import androidx.preference.SwitchPreferenceCompat
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.settingslib.preference.createAndBindWidget
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.stub
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class WifiSwitchPreferenceTest {
|
||||
|
||||
private var mockWifiManager = mock<WifiManager>()
|
||||
|
||||
private val context =
|
||||
object : ContextWrapper(ApplicationProvider.getApplicationContext()) {
|
||||
override fun getSystemService(name: String): Any? =
|
||||
when (name) {
|
||||
getSystemServiceName(WifiManager::class.java) -> mockWifiManager
|
||||
else -> super.getSystemService(name)
|
||||
}
|
||||
}
|
||||
|
||||
private val wifiSwitchPreference = WifiSwitchPreference()
|
||||
|
||||
@Test
|
||||
fun getValue_defaultOn_returnOn() {
|
||||
mockWifiManager.stub { on { isWifiEnabled } doReturn true }
|
||||
|
||||
val getValue = wifiSwitchPreference
|
||||
.storage(context)
|
||||
.getValue(WifiSwitchPreference.KEY, Boolean::class.javaObjectType)
|
||||
|
||||
assertThat(getValue).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getValue_defaultOff_returnOff() {
|
||||
mockWifiManager.stub { on { isWifiEnabled } doReturn false }
|
||||
|
||||
val getValue = wifiSwitchPreference
|
||||
.storage(context)
|
||||
.getValue(WifiSwitchPreference.KEY, Boolean::class.javaObjectType)
|
||||
|
||||
assertThat(getValue).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun performClick_defaultOn_checkedIsFalse() {
|
||||
mockWifiManager.stub { on { isWifiEnabled } doReturn true }
|
||||
|
||||
val preference = getSwitchPreference().apply { performClick() }
|
||||
|
||||
assertThat(preference.isChecked).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun performClick_defaultOff_checkedIsTrue() {
|
||||
mockWifiManager.stub { on { isWifiEnabled } doReturn false }
|
||||
|
||||
val preference = getSwitchPreference().apply { performClick() }
|
||||
|
||||
assertThat(preference.isChecked).isTrue()
|
||||
}
|
||||
|
||||
private fun getSwitchPreference(): SwitchPreferenceCompat =
|
||||
wifiSwitchPreference.createAndBindWidget(context)
|
||||
}
|
Reference in New Issue
Block a user