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