blob: 3ff80616142cefbce6485eaeab5d14f3f6bdce77 [file] [log] [blame]
Irfan Sheriffb8c0e002013-02-20 14:19:54 -08001/*
2 * Copyright (C) 2013 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
17package com.android.server.wifi;
18
19import android.content.ContentResolver;
20import android.content.Context;
21import android.provider.Settings;
22
23import java.io.FileDescriptor;
24import java.io.PrintWriter;
25
26/* Tracks persisted settings for Wi-Fi and airplane mode interaction */
27final class WifiSettingsStore {
28 /* Values tracked in Settings.Global.WIFI_ON */
29 private static final int WIFI_DISABLED = 0;
30 private static final int WIFI_ENABLED = 1;
31 /* Wifi enabled while in airplane mode */
32 private static final int WIFI_ENABLED_AIRPLANE_OVERRIDE = 2;
33 /* Wifi disabled due to airplane mode on */
34 private static final int WIFI_DISABLED_AIRPLANE_ON = 3;
35
36 /* Persisted state that tracks the wifi & airplane interaction from settings */
37 private int mPersistWifiState = WIFI_DISABLED;
38 /* Tracks current airplane mode state */
39 private boolean mAirplaneModeOn = false;
Irfan Sheriff11aefad2013-03-06 07:57:41 -080040
41 /* Tracks the setting of scan being available even when wi-fi is turned off
42 */
43 private boolean mScanAlwaysAvailable;
44
Irfan Sheriffb8c0e002013-02-20 14:19:54 -080045 private final Context mContext;
46
47 /* Tracks if we have checked the saved wi-fi state after boot */
48 private boolean mCheckSavedStateAtBoot = false;
49
50 WifiSettingsStore(Context context) {
51 mContext = context;
52 mAirplaneModeOn = getPersistedAirplaneModeOn();
53 mPersistWifiState = getPersistedWifiState();
Vinit Deshpande21833982013-07-03 00:10:53 +000054 mScanAlwaysAvailable = getPersistedScanAlwaysAvailable();
Irfan Sheriffb8c0e002013-02-20 14:19:54 -080055 }
56
Irfan Sheriff11aefad2013-03-06 07:57:41 -080057 synchronized boolean isWifiToggleEnabled() {
Irfan Sheriffb8c0e002013-02-20 14:19:54 -080058 if (!mCheckSavedStateAtBoot) {
59 mCheckSavedStateAtBoot = true;
60 if (testAndClearWifiSavedState()) return true;
61 }
62
63 if (mAirplaneModeOn) {
64 return mPersistWifiState == WIFI_ENABLED_AIRPLANE_OVERRIDE;
65 } else {
66 return mPersistWifiState != WIFI_DISABLED;
67 }
68 }
69
70 /**
71 * Returns true if airplane mode is currently on.
72 * @return {@code true} if airplane mode is on.
73 */
74 synchronized boolean isAirplaneModeOn() {
75 return mAirplaneModeOn;
76 }
77
Irfan Sheriff11aefad2013-03-06 07:57:41 -080078 synchronized boolean isScanAlwaysAvailable() {
79 return mScanAlwaysAvailable;
80 }
81
Irfan Sheriff8a64b1a2013-02-20 15:12:41 -080082 synchronized boolean handleWifiToggled(boolean wifiEnabled) {
83 // Can Wi-Fi be toggled in airplane mode ?
84 if (mAirplaneModeOn && !isAirplaneToggleable()) {
85 return false;
86 }
87
Irfan Sheriffb8c0e002013-02-20 14:19:54 -080088 if (wifiEnabled) {
Irfan Sheriff8a64b1a2013-02-20 15:12:41 -080089 if (mAirplaneModeOn) {
Irfan Sheriffb8c0e002013-02-20 14:19:54 -080090 persistWifiState(WIFI_ENABLED_AIRPLANE_OVERRIDE);
91 } else {
92 persistWifiState(WIFI_ENABLED);
93 }
94 } else {
95 // When wifi state is disabled, we do not care
96 // if airplane mode is on or not. The scenario of
97 // wifi being disabled due to airplane mode being turned on
98 // is handled handleAirplaneModeToggled()
99 persistWifiState(WIFI_DISABLED);
100 }
Irfan Sheriff8a64b1a2013-02-20 15:12:41 -0800101 return true;
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800102 }
103
Irfan Sheriff8a64b1a2013-02-20 15:12:41 -0800104 synchronized boolean handleAirplaneModeToggled() {
105 // Is Wi-Fi sensitive to airplane mode changes ?
106 if (!isAirplaneSensitive()) {
107 return false;
108 }
109
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800110 mAirplaneModeOn = getPersistedAirplaneModeOn();
111 if (mAirplaneModeOn) {
112 // Wifi disabled due to airplane on
113 if (mPersistWifiState == WIFI_ENABLED) {
114 persistWifiState(WIFI_DISABLED_AIRPLANE_ON);
115 }
116 } else {
117 /* On airplane mode disable, restore wifi state if necessary */
118 if (testAndClearWifiSavedState() ||
119 mPersistWifiState == WIFI_ENABLED_AIRPLANE_OVERRIDE) {
120 persistWifiState(WIFI_ENABLED);
121 }
122 }
Irfan Sheriff8a64b1a2013-02-20 15:12:41 -0800123 return true;
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800124 }
125
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800126 synchronized void handleWifiScanAlwaysAvailableToggled() {
Vinit Deshpande21833982013-07-03 00:10:53 +0000127 mScanAlwaysAvailable = getPersistedScanAlwaysAvailable();
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800128 }
129
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800130 void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
131 pw.println("mPersistWifiState " + mPersistWifiState);
132 pw.println("mAirplaneModeOn " + mAirplaneModeOn);
133 }
134
135 private void persistWifiState(int state) {
136 final ContentResolver cr = mContext.getContentResolver();
137 mPersistWifiState = state;
138 Settings.Global.putInt(cr, Settings.Global.WIFI_ON, state);
139 }
140
141 /* Does Wi-Fi need to be disabled when airplane mode is on ? */
142 private boolean isAirplaneSensitive() {
143 String airplaneModeRadios = Settings.Global.getString(mContext.getContentResolver(),
144 Settings.Global.AIRPLANE_MODE_RADIOS);
145 return airplaneModeRadios == null
146 || airplaneModeRadios.contains(Settings.Global.RADIO_WIFI);
147 }
148
149 /* Is Wi-Fi allowed to be re-enabled while airplane mode is on ? */
150 private boolean isAirplaneToggleable() {
151 String toggleableRadios = Settings.Global.getString(mContext.getContentResolver(),
152 Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
153 return toggleableRadios != null
154 && toggleableRadios.contains(Settings.Global.RADIO_WIFI);
155 }
156
157 /* After a reboot, we restore wi-fi to be on if it was turned off temporarily for tethering.
158 * The settings app tracks the saved state, but the framework has to check it at boot to
159 * make sure the wi-fi is turned on in case it was turned off for the purpose of tethering.
160 *
161 * Note that this is not part of the regular WIFI_ON setting because this only needs to
162 * be controlled through the settings app and not the Wi-Fi public API.
163 */
164 private boolean testAndClearWifiSavedState() {
165 final ContentResolver cr = mContext.getContentResolver();
166 int wifiSavedState = 0;
167 try {
168 wifiSavedState = Settings.Global.getInt(cr, Settings.Global.WIFI_SAVED_STATE);
169 if(wifiSavedState == 1)
170 Settings.Global.putInt(cr, Settings.Global.WIFI_SAVED_STATE, 0);
171 } catch (Settings.SettingNotFoundException e) {
172 ;
173 }
174 return (wifiSavedState == 1);
175 }
176
177 private int getPersistedWifiState() {
178 final ContentResolver cr = mContext.getContentResolver();
179 try {
180 return Settings.Global.getInt(cr, Settings.Global.WIFI_ON);
181 } catch (Settings.SettingNotFoundException e) {
182 Settings.Global.putInt(cr, Settings.Global.WIFI_ON, WIFI_DISABLED);
183 return WIFI_DISABLED;
184 }
185 }
186
187 private boolean getPersistedAirplaneModeOn() {
Irfan Sheriff8a64b1a2013-02-20 15:12:41 -0800188 return Settings.Global.getInt(mContext.getContentResolver(),
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800189 Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
190 }
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800191
192 private boolean getPersistedScanAlwaysAvailable() {
193 return Settings.Global.getInt(mContext.getContentResolver(),
194 Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE,
195 0) == 1;
196 }
Irfan Sheriffb8c0e002013-02-20 14:19:54 -0800197}