• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.wifi
18 
19 import android.Manifest
20 import android.app.settings.SettingsEnums.ACTION_WIFI
21 import android.app.settings.SettingsEnums.ACTION_WIFI_OFF
22 import android.app.settings.SettingsEnums.ACTION_WIFI_ON
23 import android.content.BroadcastReceiver
24 import android.content.Context
25 import android.content.Intent
26 import android.content.IntentFilter
27 import android.net.wifi.WifiManager
28 import android.os.UserManager
29 import android.provider.Settings
30 import android.widget.Toast
31 import androidx.preference.Preference
32 import androidx.preference.Preference.OnPreferenceChangeListener
33 import com.android.settings.R
34 import com.android.settings.contract.KEY_WIFI
35 import com.android.settings.metrics.PreferenceActionMetricsProvider
36 import com.android.settings.network.SatelliteRepository.Companion.isSatelliteOn
37 import com.android.settings.network.SatelliteWarningDialogActivity
38 import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
39 import com.android.settings.restriction.PreferenceRestrictionMixin
40 import com.android.settings.wifi.utils.isDefaultNetworkWifi
41 import com.android.settings.wifi.utils.isWifiEnabled
42 import com.android.settings.wifi.utils.wifiManager
43 import com.android.settingslib.RestrictedSwitchPreference
44 import com.android.settingslib.WirelessUtils
45 import com.android.settingslib.datastore.AbstractKeyedDataObservable
46 import com.android.settingslib.datastore.KeyValueStore
47 import com.android.settingslib.datastore.Permissions
48 import com.android.settingslib.metadata.PreferenceChangeReason
49 import com.android.settingslib.metadata.PreferenceLifecycleProvider
50 import com.android.settingslib.metadata.PreferenceMetadata
51 import com.android.settingslib.metadata.ReadWritePermit
52 import com.android.settingslib.metadata.SensitivityLevel
53 import com.android.settingslib.metadata.SwitchPreference
54 import com.android.settingslib.preference.SwitchPreferenceBinding
55 
56 // LINT.IfChange
57 class WifiSwitchPreference :
58     SwitchPreference(KEY, R.string.wifi),
59     SwitchPreferenceBinding,
60     PreferenceActionMetricsProvider,
61     OnPreferenceChangeListener,
62     PreferenceLifecycleProvider,
63     PreferenceRestrictionMixin {
64 
65     override val keywords: Int
66         get() = R.string.keywords_wifi
67 
68     override val preferenceActionMetrics: Int
69         get() = ACTION_WIFI
70 
tagsnull71     override fun tags(context: Context) = arrayOf(KEY_WIFI)
72 
73     override fun isEnabled(context: Context) = super<PreferenceRestrictionMixin>.isEnabled(context)
74 
75     override val restrictionKeys
76         get() = arrayOf(UserManager.DISALLOW_CHANGE_WIFI_STATE)
77 
78     override val useAdminDisabledSummary: Boolean
79         get() = true
80 
81     override fun createWidget(context: Context) = RestrictedSwitchPreference(context)
82 
83     override fun bind(preference: Preference, metadata: PreferenceMetadata) {
84         super.bind(preference, metadata)
85         preference.onPreferenceChangeListener = this
86     }
87 
onPreferenceChangenull88     override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
89         val context = preference.context
90 
91         // Show dialog and do nothing under satellite mode.
92         if (isSatelliteOn(context)) {
93             context.startActivity(
94                 Intent(context, SatelliteWarningDialogActivity::class.java)
95                     .putExtra(
96                         SatelliteWarningDialogActivity.EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG,
97                         SatelliteWarningDialogActivity.TYPE_IS_WIFI,
98                     )
99             )
100             return false
101         }
102 
103         // Show toast message if Wi-Fi is not allowed in airplane mode
104         if (newValue == true && !context.isRadioAllowed()) {
105             Toast.makeText(context, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show()
106             return false
107         }
108 
109         return true
110     }
111 
getReadPermissionsnull112     override fun getReadPermissions(context: Context) =
113         Permissions.allOf(Manifest.permission.ACCESS_WIFI_STATE)
114 
115     override fun getWritePermissions(context: Context) =
116         Permissions.anyOf(
117             Manifest.permission.NETWORK_SETTINGS,
118             Manifest.permission.CHANGE_WIFI_STATE,
119         )
120 
121     override fun getReadPermit(context: Context, callingPid: Int, callingUid: Int) =
122         ReadWritePermit.ALLOW
123 
124     override fun getWritePermit(
125         context: Context,
126         value: Boolean?,
127         callingPid: Int,
128         callingUid: Int,
129     ) =
130         when {
131             (value == true && !context.isRadioAllowed()) || isSatelliteOn(context) ->
132                 ReadWritePermit.DISALLOW
133             else -> ReadWritePermit.ALLOW
134         }
135 
136     override val sensitivityLevel
137         get() = SensitivityLevel.LOW_SENSITIVITY
138 
storagenull139     override fun storage(context: Context): KeyValueStore = WifiSwitchStore(context)
140 
141     @Suppress("UNCHECKED_CAST")
142     private class WifiSwitchStore(private val context: Context) :
143         AbstractKeyedDataObservable<String>(), KeyValueStore {
144 
145         private var broadcastReceiver: BroadcastReceiver? = null
146 
147         override fun contains(key: String) = key == KEY && context.wifiManager != null
148 
149         override fun <T : Any> getValue(key: String, valueType: Class<T>): T? =
150             context.isWifiEnabled as T?
151 
152         override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
153             if (value !is Boolean) return
154 
155             context.isWifiEnabled = value
156 
157             val metricsFeature = featureFactory.metricsFeatureProvider
158             if (value) {
159                 metricsFeature.action(context, ACTION_WIFI_ON)
160             } else {
161                 metricsFeature.action(context, ACTION_WIFI_OFF, context.isDefaultNetworkWifi)
162             }
163         }
164 
165         override fun onFirstObserverAdded() {
166             broadcastReceiver =
167                 object : BroadcastReceiver() {
168                     override fun onReceive(context: Context, intent: Intent) {
169                         val wifiState = intent.wifiState
170                         // do not notify for enabling/disabling state
171                         if (
172                             wifiState == WifiManager.WIFI_STATE_ENABLED ||
173                                 wifiState == WifiManager.WIFI_STATE_DISABLED
174                         ) {
175                             notifyChange(KEY, PreferenceChangeReason.VALUE)
176                         }
177                     }
178                 }
179             context.registerReceiver(
180                 broadcastReceiver,
181                 IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION),
182             )
183         }
184 
185         override fun onLastObserverRemoved() {
186             broadcastReceiver?.let { context.unregisterReceiver(it) }
187         }
188     }
189 
190     companion object {
191         const val KEY = "main_toggle_wifi"
192 
Contextnull193         private fun Context.isRadioAllowed() =
194             WirelessUtils.isRadioAllowed(this, Settings.Global.RADIO_WIFI)
195 
196         private val Intent.wifiState
197             get() = getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN)
198     }
199 }
200 // LINT.ThenChange(WifiSwitchPreferenceController.java)
201