1 /*
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 
17 package com.android.server.wifi;
18 
19 import android.app.ActivityManager;
20 import android.app.Notification;
21 import android.app.PendingIntent;
22 import android.content.ContentResolver;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.graphics.drawable.Icon;
26 import android.net.Uri;
27 import android.net.wifi.WifiContext;
28 import android.provider.Settings;
29 
30 import com.android.internal.annotations.VisibleForTesting;
31 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
32 import com.android.wifi.resources.R;
33 
34 import java.io.FileDescriptor;
35 import java.io.PrintWriter;
36 
37 /* Tracks persisted settings for Wi-Fi and airplane mode interaction */
38 public class WifiSettingsStore {
39     /* Values used to track the current state of Wi-Fi
40      * Key: Settings.Global.WIFI_ON
41      * Values:
42      *     WIFI_DISABLED
43      *     WIFI_ENABLED
44      *     WIFI_ENABLED_APM_OVERRIDE
45      *     WIFI_DISABLED_APM_ON
46      */
47     private static final String TAG = "WifiSettingsStore";
48     @VisibleForTesting
49     public static final int WIFI_DISABLED                      = 0;
50     @VisibleForTesting
51     public static final int WIFI_ENABLED                       = 1;
52     /* Wifi enabled while in airplane mode */
53     @VisibleForTesting
54     public static final int WIFI_ENABLED_APM_OVERRIDE = 2;
55     /* Wifi disabled due to airplane mode on */
56     @VisibleForTesting
57     public static final int WIFI_DISABLED_APM_ON = 3;
58 
59     /* Values used to track the current state of airplane mode
60      * Key: Settings.Global.AIRPLANE_MODE_ON
61      * Values:
62      *     APM_DISABLED
63      *     APM_ENABLED
64      */
65     @VisibleForTesting
66     public static final int APM_DISABLED                      = 0;
67     @VisibleForTesting
68     public static final int APM_ENABLED                       = 1;
69 
70     /* Values used to track whether Wi-Fi should remain on in airplane mode
71      * Key: Settings.Secure WIFI_APM_STATE
72      * Values:
73      *     WIFI_TURNS_OFF_IN_APM
74      *     WIFI_REMAINS_ON_IN_APM
75      */
76     @VisibleForTesting
77     public static final String WIFI_APM_STATE = "wifi_apm_state";
78     @VisibleForTesting
79     public static final int WIFI_TURNS_OFF_IN_APM = 0;
80     @VisibleForTesting
81     public static final int WIFI_REMAINS_ON_IN_APM = 1;
82 
83     /* Values used to track whether Bluetooth should remain on in airplane mode
84      * Key: Settings.Secure BLUETOOTH_APM_STATE
85      * Values:
86      *     BT_TURNS_OFF_IN_APM
87      *     BT_REMAINS_ON_IN_APM
88      */
89     @VisibleForTesting
90     public static final String BLUETOOTH_APM_STATE = "bluetooth_apm_state";
91     @VisibleForTesting
92     public static final int BT_TURNS_OFF_IN_APM = 0;
93     @VisibleForTesting
94     public static final int BT_REMAINS_ON_IN_APM = 1;
95 
96     /* Values used to track whether a notification has been shown
97      * Keys:
98      *     Settings.Secure APM_WIFI_NOTIFICATION
99      *     Settings.Secure APM_WIFI_ENABLED_NOTIFICATION
100      * Values:
101      *     NOTIFICATION_NOT_SHOWN
102      *     NOTIFICATION_SHOWN
103      */
104     /* Track whether Wi-Fi remains on in airplane mode notification was shown */
105     @VisibleForTesting
106     public static final String APM_WIFI_NOTIFICATION = "apm_wifi_notification";
107     /* Track whether Wi-Fi enabled in airplane mode notification was shown */
108     @VisibleForTesting
109     public static final String APM_WIFI_ENABLED_NOTIFICATION = "apm_wifi_enabled_notification";
110     @VisibleForTesting
111     public static final int NOTIFICATION_NOT_SHOWN = 0;
112     @VisibleForTesting
113     public static final int NOTIFICATION_SHOWN = 1;
114 
115     /**
116      * @hide constant copied from {@link Settings.Global}
117      * TODO(b/274636414): Migrate to official API in Android V.
118      */
119     static final String SETTINGS_SATELLITE_MODE_RADIOS = "satellite_mode_radios";
120     /**
121      * @hide constant copied from {@link Settings.Global}
122      * TODO(b/274636414): Migrate to official API in Android V.
123      */
124     static final String SETTINGS_SATELLITE_MODE_ENABLED = "satellite_mode_enabled";
125 
126     /* Persisted state that tracks the wifi & airplane interaction from settings */
127     private int mPersistWifiState = WIFI_DISABLED;
128 
129     /* Tracks current airplane mode state */
130     private boolean mAirplaneModeOn = false;
131 
132     /* Tracks the wifi state before entering airplane mode*/
133     private boolean mIsWifiOnBeforeEnteringApm = false;
134 
135     /* Tracks the wifi state after entering airplane mode*/
136     private boolean mIsWifiOnAfterEnteringApm = false;
137 
138     /* Tracks whether user toggled wifi in airplane mode */
139     private boolean mUserToggledWifiDuringApm = false;
140 
141     /* Tracks whether user toggled wifi within one minute of entering airplane mode */
142     private boolean mUserToggledWifiAfterEnteringApmWithinMinute = false;
143 
144     /* Tracks when airplane mode has been enabled in milliseconds since boot */
145     private long mApmEnabledTimeSinceBootMillis = 0;
146 
147     private final String mApmEnhancementHelpLink;
148     private final WifiContext mContext;
149     private final WifiSettingsConfigStore mSettingsConfigStore;
150     private final WifiThreadRunner mWifiThreadRunner;
151     private final FrameworkFacade mFrameworkFacade;
152     private final WifiNotificationManager mNotificationManager;
153     private final DeviceConfigFacade mDeviceConfigFacade;
154     private final WifiMetrics mWifiMetrics;
155     private final Clock mClock;
156     private boolean mSatelliteModeOn;
157 
WifiSettingsStore(WifiContext context, WifiSettingsConfigStore sharedPreferences, WifiThreadRunner wifiThread, FrameworkFacade frameworkFacade, WifiNotificationManager notificationManager, DeviceConfigFacade deviceConfigFacade, WifiMetrics wifiMetrics, Clock clock)158     WifiSettingsStore(WifiContext context, WifiSettingsConfigStore sharedPreferences,
159             WifiThreadRunner wifiThread, FrameworkFacade frameworkFacade,
160             WifiNotificationManager notificationManager, DeviceConfigFacade deviceConfigFacade,
161             WifiMetrics wifiMetrics, Clock clock) {
162         mContext = context;
163         mSettingsConfigStore = sharedPreferences;
164         mWifiThreadRunner = wifiThread;
165         mFrameworkFacade = frameworkFacade;
166         mNotificationManager = notificationManager;
167         mDeviceConfigFacade = deviceConfigFacade;
168         mWifiMetrics = wifiMetrics;
169         mClock = clock;
170         mAirplaneModeOn = getPersistedAirplaneModeOn();
171         mPersistWifiState = getPersistedWifiState();
172         mApmEnhancementHelpLink = mContext.getString(R.string.config_wifiApmEnhancementHelpLink);
173         mSatelliteModeOn = getPersistedSatelliteModeOn();
174     }
175 
getUserSecureIntegerSetting(String name, int def)176     private int getUserSecureIntegerSetting(String name, int def) {
177         Context userContext = mFrameworkFacade.getUserContext(mContext);
178         return mFrameworkFacade.getSecureIntegerSetting(userContext, name, def);
179     }
180 
setUserSecureIntegerSetting(String name, int value)181     private void setUserSecureIntegerSetting(String name, int value) {
182         Context userContext = mFrameworkFacade.getUserContext(mContext);
183         mFrameworkFacade.setSecureIntegerSetting(userContext, name, value);
184     }
185 
isWifiToggleEnabled()186     public synchronized boolean isWifiToggleEnabled() {
187         return mPersistWifiState == WIFI_ENABLED
188                 || mPersistWifiState == WIFI_ENABLED_APM_OVERRIDE;
189     }
190 
191     /**
192      * Returns true if airplane mode is currently on.
193      * @return {@code true} if airplane mode is on.
194      */
isAirplaneModeOn()195     public synchronized boolean isAirplaneModeOn() {
196         return mAirplaneModeOn;
197     }
198 
isScanAlwaysAvailableToggleEnabled()199     public synchronized boolean isScanAlwaysAvailableToggleEnabled() {
200         return getPersistedScanAlwaysAvailable();
201     }
202 
isScanAlwaysAvailable()203     public synchronized boolean isScanAlwaysAvailable() {
204         return !mAirplaneModeOn && getPersistedScanAlwaysAvailable();
205     }
206 
isWifiScoringEnabled()207     public synchronized boolean isWifiScoringEnabled() {
208         return getPersistedWifiScoringEnabled();
209     }
210 
isWifiPasspointEnabled()211     public synchronized boolean isWifiPasspointEnabled() {
212         return getPersistedWifiPasspointEnabled();
213     }
214 
isWifiScanThrottleEnabled()215     public synchronized boolean isWifiScanThrottleEnabled() {
216         return getPersistedWifiScanThrottleEnabled();
217     }
218 
getWifiMultiInternetMode()219     public synchronized int getWifiMultiInternetMode() {
220         return getPersistedWifiMultiInternetMode();
221     }
222 
setPersistWifiState(int state)223     public void setPersistWifiState(int state) {
224         mPersistWifiState = state;
225     }
226 
showNotification(int titleId, int messageId)227     private void showNotification(int titleId, int messageId) {
228         String settingsPackage = mFrameworkFacade.getSettingsPackageName(mContext);
229         if (settingsPackage == null) return;
230 
231         Intent openLinkIntent = new Intent(Intent.ACTION_VIEW)
232                 .setData(Uri.parse(mApmEnhancementHelpLink))
233                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
234         PendingIntent tapPendingIntent = mFrameworkFacade.getActivity(mContext, 0, openLinkIntent,
235                 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
236 
237         String title = mContext.getResources().getString(titleId);
238         String message = mContext.getResources().getString(messageId);
239         Notification.Builder builder = mFrameworkFacade.makeNotificationBuilder(mContext,
240                         WifiService.NOTIFICATION_APM_ALERTS)
241                 .setAutoCancel(true)
242                 .setLocalOnly(true)
243                 .setContentTitle(title)
244                 .setContentText(message)
245                 .setContentIntent(tapPendingIntent)
246                 .setVisibility(Notification.VISIBILITY_PUBLIC)
247                 .setStyle(new Notification.BigTextStyle().bigText(message))
248                 .setSmallIcon(Icon.createWithResource(mContext.getWifiOverlayApkPkgName(),
249                         R.drawable.ic_wifi_settings));
250         mNotificationManager.notify(SystemMessage.NOTE_WIFI_APM_NOTIFICATION, builder.build());
251     }
252 
handleWifiToggled(boolean wifiEnabled)253     public synchronized boolean handleWifiToggled(boolean wifiEnabled) {
254         // Can Wi-Fi be toggled in airplane mode ?
255         if (mAirplaneModeOn && !isAirplaneToggleable()) {
256             return false;
257         }
258         if (wifiEnabled) {
259             if (mAirplaneModeOn) {
260                 persistWifiState(WIFI_ENABLED_APM_OVERRIDE);
261                 if (mDeviceConfigFacade.isApmEnhancementEnabled()) {
262                     setUserSecureIntegerSetting(WIFI_APM_STATE, WIFI_REMAINS_ON_IN_APM);
263                     if (getUserSecureIntegerSetting(APM_WIFI_ENABLED_NOTIFICATION,
264                             NOTIFICATION_NOT_SHOWN) == NOTIFICATION_NOT_SHOWN) {
265                         mWifiThreadRunner.post(
266                                 () -> showNotification(R.string.wifi_enabled_apm_first_time_title,
267                                         R.string.wifi_enabled_apm_first_time_message),
268                                 TAG + "#handleWifiToggled");
269                         setUserSecureIntegerSetting(
270                                 APM_WIFI_ENABLED_NOTIFICATION, NOTIFICATION_SHOWN);
271                     }
272                 }
273             } else {
274                 persistWifiState(WIFI_ENABLED);
275             }
276         } else {
277             // When wifi state is disabled, we do not care
278             // if airplane mode is on or not. The scenario of
279             // wifi being disabled due to airplane mode being turned on
280             // is handled handleAirplaneModeToggled()
281             persistWifiState(WIFI_DISABLED);
282             if (mDeviceConfigFacade.isApmEnhancementEnabled() && mAirplaneModeOn) {
283                 setUserSecureIntegerSetting(WIFI_APM_STATE, WIFI_TURNS_OFF_IN_APM);
284             }
285         }
286         if (mAirplaneModeOn) {
287             if (!mUserToggledWifiDuringApm) {
288                 mUserToggledWifiAfterEnteringApmWithinMinute =
289                         mClock.getElapsedSinceBootMillis() - mApmEnabledTimeSinceBootMillis
290                                 < 60_000;
291             }
292             mUserToggledWifiDuringApm = true;
293         }
294         return true;
295     }
296 
297     synchronized boolean updateAirplaneModeTracker() {
298         // Is Wi-Fi sensitive to airplane mode changes ?
299         if (!isAirplaneSensitive()) {
300             return false;
301         }
302 
303         mAirplaneModeOn = getPersistedAirplaneModeOn();
304         return true;
305     }
306 
307     synchronized void handleAirplaneModeToggled() {
308         if (mAirplaneModeOn) {
309             mApmEnabledTimeSinceBootMillis = mClock.getElapsedSinceBootMillis();
310             mIsWifiOnBeforeEnteringApm = mPersistWifiState == WIFI_ENABLED;
311             if (mPersistWifiState == WIFI_ENABLED) {
312                 if (mDeviceConfigFacade.isApmEnhancementEnabled()
313                         && getUserSecureIntegerSetting(WIFI_APM_STATE, WIFI_TURNS_OFF_IN_APM)
314                         == WIFI_REMAINS_ON_IN_APM) {
315                     persistWifiState(WIFI_ENABLED_APM_OVERRIDE);
316                     if (getUserSecureIntegerSetting(APM_WIFI_NOTIFICATION, NOTIFICATION_NOT_SHOWN)
317                             == NOTIFICATION_NOT_SHOWN
318                             && !isBluetoothEnabledOnApm()) {
319                         mWifiThreadRunner.post(
320                                 () -> showNotification(R.string.apm_enabled_first_time_title,
321                                         R.string.apm_enabled_first_time_message),
322                                 TAG + "#handleAirplaneModeToggled");
323                         setUserSecureIntegerSetting(APM_WIFI_NOTIFICATION, NOTIFICATION_SHOWN);
324                     }
325                 } else {
326                     // Wifi disabled due to airplane on
327                     persistWifiState(WIFI_DISABLED_APM_ON);
328                 }
329             }
330             mIsWifiOnAfterEnteringApm = mPersistWifiState == WIFI_ENABLED_APM_OVERRIDE;
331         } else {
mWifiMetrics.reportAirplaneModeSession(mIsWifiOnBeforeEnteringApm, mIsWifiOnAfterEnteringApm, mPersistWifiState == WIFI_ENABLED_APM_OVERRIDE, getUserSecureIntegerSetting(APM_WIFI_ENABLED_NOTIFICATION, NOTIFICATION_NOT_SHOWN) == NOTIFICATION_SHOWN, mUserToggledWifiDuringApm, mUserToggledWifiAfterEnteringApmWithinMinute)332             mWifiMetrics.reportAirplaneModeSession(mIsWifiOnBeforeEnteringApm,
333                     mIsWifiOnAfterEnteringApm,
334                     mPersistWifiState == WIFI_ENABLED_APM_OVERRIDE,
335                     getUserSecureIntegerSetting(APM_WIFI_ENABLED_NOTIFICATION,
336                             NOTIFICATION_NOT_SHOWN) == NOTIFICATION_SHOWN,
337                     mUserToggledWifiDuringApm, mUserToggledWifiAfterEnteringApmWithinMinute);
338             mUserToggledWifiDuringApm = false;
339             mUserToggledWifiAfterEnteringApmWithinMinute = false;
340 
341             /* On airplane mode disable, restore wifi state if necessary */
342             if (mPersistWifiState == WIFI_ENABLED_APM_OVERRIDE
343                     || mPersistWifiState == WIFI_DISABLED_APM_ON) {
344                 persistWifiState(WIFI_ENABLED);
345             }
346         }
347     }
348 
349     synchronized void handleWifiScanAlwaysAvailableToggled(boolean isAvailable) {
350         persistScanAlwaysAvailableState(isAvailable);
351     }
352 
353     synchronized boolean handleWifiScoringEnabled(boolean enabled) {
354         persistWifiScoringEnabledState(enabled);
355         return true;
356     }
357 
358     /**
359      * Handle the Wifi Passpoint enable/disable status change.
360      */
361     public synchronized void handleWifiPasspointEnabled(boolean enabled) {
362         persistWifiPasspointEnabledState(enabled);
363     }
364 
365     /**
366      * Handle the Wifi Multi Internet state change.
367      */
368     public synchronized void handleWifiMultiInternetMode(int mode) {
369         persistWifiMultiInternetMode(mode);
370     }
371 
372     /**
373      * Indicate whether Wi-Fi should remain on when airplane mode is enabled
374      */
375     public boolean shouldWifiRemainEnabledWhenApmEnabled() {
376         return mDeviceConfigFacade.isApmEnhancementEnabled()
377                 && isWifiToggleEnabled()
378                 && (getUserSecureIntegerSetting(WIFI_APM_STATE,
379                 WIFI_TURNS_OFF_IN_APM) == WIFI_REMAINS_ON_IN_APM);
380     }
381 
382     private boolean isBluetoothEnabledOnApm() {
383         return mFrameworkFacade.getIntegerSetting(mContext.getContentResolver(),
384                 Settings.Global.BLUETOOTH_ON, 0) != 0
385                 && getUserSecureIntegerSetting(BLUETOOTH_APM_STATE, BT_TURNS_OFF_IN_APM)
386                 == BT_REMAINS_ON_IN_APM;
387     }
388 
389     synchronized void updateSatelliteModeTracker() {
390         mSatelliteModeOn = getPersistedSatelliteModeOn();
391     }
392 
393     public boolean isSatelliteModeOn() {
394         return mSatelliteModeOn;
395     }
396 
397     void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
398         pw.println("WifiState " + getPersistedWifiState());
399         pw.println("AirplaneModeOn " + getPersistedAirplaneModeOn());
400         pw.println("ScanAlwaysAvailable " + getPersistedScanAlwaysAvailable());
401         pw.println("WifiScoringState " + getPersistedWifiScoringEnabled());
402         pw.println("WifiPasspointState " + getPersistedWifiPasspointEnabled());
403         pw.println("WifiMultiInternetMode " + getPersistedWifiMultiInternetMode());
404         pw.println("WifiStateApm " + (getUserSecureIntegerSetting(WIFI_APM_STATE,
405                 WIFI_TURNS_OFF_IN_APM) == WIFI_REMAINS_ON_IN_APM));
406         pw.println("WifiStateBt " + isBluetoothEnabledOnApm());
407         pw.println("WifiStateUser " + ActivityManager.getCurrentUser());
408         pw.println("AirplaneModeEnhancementEnabled "
409                 + mDeviceConfigFacade.isApmEnhancementEnabled());
410         if (mAirplaneModeOn) {
411             pw.println("WifiOnBeforeEnteringApm " + mIsWifiOnBeforeEnteringApm);
412             pw.println("WifiOnAfterEnteringApm " + mIsWifiOnAfterEnteringApm);
413             pw.println("UserToggledWifiDuringApm " + mUserToggledWifiDuringApm);
414             pw.println("UserToggledWifiAfterEnteringApmWithinMinute "
415                     + mUserToggledWifiAfterEnteringApmWithinMinute);
416         }
417         pw.println("SatelliteModeOn " + mSatelliteModeOn);
418     }
419 
420     private void persistWifiState(int state) {
421         final ContentResolver cr = mContext.getContentResolver();
422         mPersistWifiState = state;
423         mFrameworkFacade.setIntegerSetting(cr, Settings.Global.WIFI_ON, state);
424     }
425 
426     private void persistScanAlwaysAvailableState(boolean isAvailable) {
427         mSettingsConfigStore.put(
428                 WifiSettingsConfigStore.WIFI_SCAN_ALWAYS_AVAILABLE, isAvailable);
429     }
430 
431     private void persistWifiScoringEnabledState(boolean enabled) {
432         mSettingsConfigStore.put(
433                 WifiSettingsConfigStore.WIFI_SCORING_ENABLED, enabled);
434     }
435 
436     private void persistWifiPasspointEnabledState(boolean enabled) {
437         mSettingsConfigStore.put(
438                 WifiSettingsConfigStore.WIFI_PASSPOINT_ENABLED, enabled);
439     }
440 
441     private void persistWifiMultiInternetMode(int mode) {
442         mSettingsConfigStore.put(
443                 WifiSettingsConfigStore.WIFI_MULTI_INTERNET_MODE, mode);
444     }
445 
446     /* Does Wi-Fi need to be disabled when airplane mode is on ? */
447     private boolean isAirplaneSensitive() {
448         String airplaneModeRadios = mFrameworkFacade.getStringSetting(mContext,
449                 Settings.Global.AIRPLANE_MODE_RADIOS);
450         return airplaneModeRadios == null
451                 || airplaneModeRadios.contains(Settings.Global.RADIO_WIFI);
452     }
453 
454     /* Is Wi-Fi allowed to be re-enabled while airplane mode is on ? */
455     private boolean isAirplaneToggleable() {
456         String toggleableRadios = mFrameworkFacade.getStringSetting(mContext,
457                 Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
458         return toggleableRadios != null
459                 && toggleableRadios.contains(Settings.Global.RADIO_WIFI);
460     }
461 
462     private int getPersistedWifiState() {
463         final ContentResolver cr = mContext.getContentResolver();
464         try {
465             return mFrameworkFacade.getIntegerSetting(cr, Settings.Global.WIFI_ON);
466         } catch (Settings.SettingNotFoundException e) {
467             mFrameworkFacade.setIntegerSetting(cr, Settings.Global.WIFI_ON, WIFI_DISABLED);
468             return WIFI_DISABLED;
469         }
470     }
471 
472     private boolean getPersistedAirplaneModeOn() {
473         return mFrameworkFacade.getIntegerSetting(mContext.getContentResolver(),
474                 Settings.Global.AIRPLANE_MODE_ON, APM_DISABLED) == APM_ENABLED;
475     }
476 
477     private boolean getPersistedScanAlwaysAvailable() {
478         return mSettingsConfigStore.get(
479                 WifiSettingsConfigStore.WIFI_SCAN_ALWAYS_AVAILABLE);
480     }
481 
482     private boolean getPersistedWifiScoringEnabled() {
483         return mSettingsConfigStore.get(
484                 WifiSettingsConfigStore.WIFI_SCORING_ENABLED);
485     }
486 
487     private boolean getPersistedWifiPasspointEnabled() {
488         return mSettingsConfigStore.get(
489                 WifiSettingsConfigStore.WIFI_PASSPOINT_ENABLED);
490     }
491 
492     private boolean getPersistedWifiScanThrottleEnabled() {
493         return mSettingsConfigStore.get(
494                 WifiSettingsConfigStore.WIFI_SCAN_THROTTLE_ENABLED);
495     }
496 
497     private int getPersistedWifiMultiInternetMode() {
498         return mSettingsConfigStore.get(
499                 WifiSettingsConfigStore.WIFI_MULTI_INTERNET_MODE);
500     }
501 
502     private boolean getPersistedIsSatelliteModeSensitive() {
503         String satelliteRadios = mFrameworkFacade.getStringSetting(mContext,
504                 SETTINGS_SATELLITE_MODE_RADIOS);
505         return satelliteRadios != null
506                 && satelliteRadios.contains(Settings.Global.RADIO_WIFI);
507     }
508 
509     /** Returns true if satellite mode is turned on. */
510     private boolean getPersistedSatelliteModeOn() {
511         if (!getPersistedIsSatelliteModeSensitive()) return false;
512         return  mFrameworkFacade.getIntegerSetting(
513                 mContext, SETTINGS_SATELLITE_MODE_ENABLED, 0) == 1;
514     }
515 }
516