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