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