1 /* 2 * Copyright (C) 2018 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 static com.android.server.wifi.ConnectToNetworkNotificationBuilder.ACTION_CONNECT_TO_NETWORK; 20 import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.ACTION_PICK_WIFI_NETWORK; 21 import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE; 22 import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.ACTION_USER_DISMISSED_NOTIFICATION; 23 import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.AVAILABLE_NETWORK_NOTIFIER_TAG; 24 25 import android.annotation.IntDef; 26 import android.annotation.NonNull; 27 import android.app.Notification; 28 import android.app.NotificationManager; 29 import android.content.BroadcastReceiver; 30 import android.content.Context; 31 import android.content.Intent; 32 import android.content.IntentFilter; 33 import android.database.ContentObserver; 34 import android.net.wifi.ScanResult; 35 import android.net.wifi.WifiConfiguration; 36 import android.net.wifi.WifiManager; 37 import android.os.Handler; 38 import android.os.Looper; 39 import android.os.Message; 40 import android.os.Messenger; 41 import android.os.Process; 42 import android.os.UserHandle; 43 import android.os.UserManager; 44 import android.provider.Settings; 45 import android.text.TextUtils; 46 import android.util.ArraySet; 47 import android.util.Log; 48 49 import com.android.internal.annotations.VisibleForTesting; 50 import com.android.server.wifi.nano.WifiMetricsProto.ConnectToNetworkNotificationAndActionCount; 51 import com.android.server.wifi.util.ScanResultUtil; 52 53 import java.io.FileDescriptor; 54 import java.io.PrintWriter; 55 import java.lang.annotation.Retention; 56 import java.lang.annotation.RetentionPolicy; 57 import java.util.List; 58 import java.util.Set; 59 60 /** 61 * Base class for all network notifiers (e.g. OpenNetworkNotifier, CarrierNetworkNotifier). 62 * 63 * NOTE: These API's are not thread safe and should only be used from WifiCoreThread. 64 */ 65 public class AvailableNetworkNotifier { 66 67 /** Time in milliseconds to display the Connecting notification. */ 68 private static final int TIME_TO_SHOW_CONNECTING_MILLIS = 10000; 69 70 /** Time in milliseconds to display the Connected notification. */ 71 private static final int TIME_TO_SHOW_CONNECTED_MILLIS = 5000; 72 73 /** Time in milliseconds to display the Failed To Connect notification. */ 74 private static final int TIME_TO_SHOW_FAILED_MILLIS = 5000; 75 76 /** The state of the notification */ 77 @IntDef({ 78 STATE_NO_NOTIFICATION, 79 STATE_SHOWING_RECOMMENDATION_NOTIFICATION, 80 STATE_CONNECTING_IN_NOTIFICATION, 81 STATE_CONNECTED_NOTIFICATION, 82 STATE_CONNECT_FAILED_NOTIFICATION 83 }) 84 @Retention(RetentionPolicy.SOURCE) 85 private @interface State {} 86 87 /** No recommendation is made and no notifications are shown. */ 88 private static final int STATE_NO_NOTIFICATION = 0; 89 /** The initial notification recommending a network to connect to is shown. */ 90 private static final int STATE_SHOWING_RECOMMENDATION_NOTIFICATION = 1; 91 /** The notification of status of connecting to the recommended network is shown. */ 92 private static final int STATE_CONNECTING_IN_NOTIFICATION = 2; 93 /** The notification that the connection to the recommended network was successful is shown. */ 94 private static final int STATE_CONNECTED_NOTIFICATION = 3; 95 /** The notification to show that connection to the recommended network failed is shown. */ 96 private static final int STATE_CONNECT_FAILED_NOTIFICATION = 4; 97 98 /** Current state of the notification. */ 99 @State private int mState = STATE_NO_NOTIFICATION; 100 101 /** 102 * The {@link Clock#getWallClockMillis()} must be at least this value for us 103 * to show the notification again. 104 */ 105 private long mNotificationRepeatTime; 106 /** 107 * When a notification is shown, we wait this amount before possibly showing it again. 108 */ 109 private final long mNotificationRepeatDelay; 110 /** Default repeat delay in seconds. */ 111 @VisibleForTesting 112 static final int DEFAULT_REPEAT_DELAY_SEC = 900; 113 114 /** Whether the user has set the setting to show the 'available networks' notification. */ 115 private boolean mSettingEnabled; 116 /** Whether the screen is on or not. */ 117 private boolean mScreenOn; 118 119 /** List of SSIDs blacklisted from recommendation. */ 120 private final Set<String> mBlacklistedSsids = new ArraySet<>(); 121 122 private final Context mContext; 123 private final Handler mHandler; 124 private final FrameworkFacade mFrameworkFacade; 125 private final WifiMetrics mWifiMetrics; 126 private final Clock mClock; 127 private final WifiConfigManager mConfigManager; 128 private final ClientModeImpl mClientModeImpl; 129 private final Messenger mSrcMessenger; 130 private final ConnectToNetworkNotificationBuilder mNotificationBuilder; 131 132 private ScanResult mRecommendedNetwork; 133 134 /** Tag used for logs and metrics */ 135 private final String mTag; 136 /** Identifier of the {@link SsidSetStoreData}. */ 137 private final String mStoreDataIdentifier; 138 /** Identifier for the settings toggle, used for registering ContentObserver */ 139 private final String mToggleSettingsName; 140 141 /** System wide identifier for notification in Notification Manager */ 142 private final int mSystemMessageNotificationId; 143 144 /** 145 * The nominator id for this class, from 146 * {@link com.android.server.wifi.nano.WifiMetricsProto.ConnectionEvent.ConnectionNominator} 147 */ 148 private final int mNominatorId; 149 AvailableNetworkNotifier( String tag, String storeDataIdentifier, String toggleSettingsName, int notificationIdentifier, int nominatorId, Context context, Looper looper, FrameworkFacade framework, Clock clock, WifiMetrics wifiMetrics, WifiConfigManager wifiConfigManager, WifiConfigStore wifiConfigStore, ClientModeImpl clientModeImpl, ConnectToNetworkNotificationBuilder connectToNetworkNotificationBuilder)150 public AvailableNetworkNotifier( 151 String tag, 152 String storeDataIdentifier, 153 String toggleSettingsName, 154 int notificationIdentifier, 155 int nominatorId, 156 Context context, 157 Looper looper, 158 FrameworkFacade framework, 159 Clock clock, 160 WifiMetrics wifiMetrics, 161 WifiConfigManager wifiConfigManager, 162 WifiConfigStore wifiConfigStore, 163 ClientModeImpl clientModeImpl, 164 ConnectToNetworkNotificationBuilder connectToNetworkNotificationBuilder) { 165 mTag = tag; 166 mStoreDataIdentifier = storeDataIdentifier; 167 mToggleSettingsName = toggleSettingsName; 168 mSystemMessageNotificationId = notificationIdentifier; 169 mNominatorId = nominatorId; 170 mContext = context; 171 mHandler = new Handler(looper); 172 mFrameworkFacade = framework; 173 mWifiMetrics = wifiMetrics; 174 mClock = clock; 175 mConfigManager = wifiConfigManager; 176 mClientModeImpl = clientModeImpl; 177 mNotificationBuilder = connectToNetworkNotificationBuilder; 178 mScreenOn = false; 179 mSrcMessenger = new Messenger(new Handler(looper, mConnectionStateCallback)); 180 wifiConfigStore.registerStoreData(new SsidSetStoreData(mStoreDataIdentifier, 181 new AvailableNetworkNotifierStoreData())); 182 183 // Setting is in seconds 184 mNotificationRepeatDelay = mFrameworkFacade.getIntegerSetting(context, 185 Settings.Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, 186 DEFAULT_REPEAT_DELAY_SEC) * 1000L; 187 NotificationEnabledSettingObserver settingObserver = new NotificationEnabledSettingObserver( 188 mHandler); 189 settingObserver.register(); 190 191 IntentFilter filter = new IntentFilter(); 192 filter.addAction(ACTION_USER_DISMISSED_NOTIFICATION); 193 filter.addAction(ACTION_CONNECT_TO_NETWORK); 194 filter.addAction(ACTION_PICK_WIFI_NETWORK); 195 filter.addAction(ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE); 196 mContext.registerReceiver( 197 mBroadcastReceiver, filter, null /* broadcastPermission */, mHandler); 198 } 199 200 private final BroadcastReceiver mBroadcastReceiver = 201 new BroadcastReceiver() { 202 @Override 203 public void onReceive(Context context, Intent intent) { 204 if (!mTag.equals(intent.getExtra(AVAILABLE_NETWORK_NOTIFIER_TAG))) { 205 return; 206 } 207 switch (intent.getAction()) { 208 case ACTION_USER_DISMISSED_NOTIFICATION: 209 handleUserDismissedAction(); 210 break; 211 case ACTION_CONNECT_TO_NETWORK: 212 handleConnectToNetworkAction(); 213 break; 214 case ACTION_PICK_WIFI_NETWORK: 215 handleSeeAllNetworksAction(); 216 break; 217 case ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE: 218 handlePickWifiNetworkAfterConnectFailure(); 219 break; 220 default: 221 Log.e(mTag, "Unknown action " + intent.getAction()); 222 } 223 } 224 }; 225 226 private final Handler.Callback mConnectionStateCallback = (Message msg) -> { 227 switch (msg.what) { 228 // Success here means that an attempt to connect to the network has been initiated. 229 // Successful connection updates are received via the 230 // WifiConnectivityManager#handleConnectionStateChanged() callback. 231 case WifiManager.CONNECT_NETWORK_SUCCEEDED: 232 break; 233 case WifiManager.CONNECT_NETWORK_FAILED: 234 handleConnectionAttemptFailedToSend(); 235 break; 236 default: 237 Log.e("AvailableNetworkNotifier", "Unknown message " + msg.what); 238 } 239 return true; 240 }; 241 242 /** 243 * Clears the pending notification. This is called by {@link WifiConnectivityManager} on stop. 244 * 245 * @param resetRepeatTime resets the time delay for repeated notification if true. 246 */ clearPendingNotification(boolean resetRepeatTime)247 public void clearPendingNotification(boolean resetRepeatTime) { 248 if (resetRepeatTime) { 249 mNotificationRepeatTime = 0; 250 } 251 252 if (mState != STATE_NO_NOTIFICATION) { 253 getNotificationManager().cancel(mSystemMessageNotificationId); 254 255 if (mRecommendedNetwork != null) { 256 Log.d(mTag, "Notification with state=" 257 + mState 258 + " was cleared for recommended network: " 259 + "\"" + mRecommendedNetwork.SSID + "\""); 260 } 261 mState = STATE_NO_NOTIFICATION; 262 mRecommendedNetwork = null; 263 } 264 } 265 isControllerEnabled()266 private boolean isControllerEnabled() { 267 return mSettingEnabled && !UserManager.get(mContext) 268 .hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, UserHandle.CURRENT); 269 } 270 271 /** 272 * If there are available networks, attempt to post a network notification. 273 * 274 * @param availableNetworks Available networks to choose from and possibly show notification 275 */ handleScanResults(@onNull List<ScanDetail> availableNetworks)276 public void handleScanResults(@NonNull List<ScanDetail> availableNetworks) { 277 if (!isControllerEnabled()) { 278 clearPendingNotification(true /* resetRepeatTime */); 279 return; 280 } 281 if (availableNetworks.isEmpty() && mState == STATE_SHOWING_RECOMMENDATION_NOTIFICATION) { 282 clearPendingNotification(false /* resetRepeatTime */); 283 return; 284 } 285 286 // Not enough time has passed to show a recommendation notification again 287 if (mState == STATE_NO_NOTIFICATION 288 && mClock.getWallClockMillis() < mNotificationRepeatTime) { 289 return; 290 } 291 292 // Do nothing when the screen is off and no notification is showing. 293 if (mState == STATE_NO_NOTIFICATION && !mScreenOn) { 294 return; 295 } 296 297 // Only show a new or update an existing recommendation notification. 298 if (mState == STATE_NO_NOTIFICATION 299 || mState == STATE_SHOWING_RECOMMENDATION_NOTIFICATION) { 300 ScanResult recommendation = 301 recommendNetwork(availableNetworks); 302 303 if (recommendation != null) { 304 postInitialNotification(recommendation); 305 } else { 306 clearPendingNotification(false /* resetRepeatTime */); 307 } 308 } 309 } 310 311 /** 312 * Recommends a network to connect to from a list of available networks, while ignoring the 313 * SSIDs in the blacklist. 314 * 315 * @param networks List of networks to select from 316 */ recommendNetwork(@onNull List<ScanDetail> networks)317 public ScanResult recommendNetwork(@NonNull List<ScanDetail> networks) { 318 ScanResult result = null; 319 int highestRssi = Integer.MIN_VALUE; 320 for (ScanDetail scanDetail : networks) { 321 ScanResult scanResult = scanDetail.getScanResult(); 322 323 if (scanResult.level > highestRssi) { 324 result = scanResult; 325 highestRssi = scanResult.level; 326 } 327 } 328 329 if (result != null && mBlacklistedSsids.contains(result.SSID)) { 330 result = null; 331 } 332 return result; 333 } 334 335 /** Handles screen state changes. */ handleScreenStateChanged(boolean screenOn)336 public void handleScreenStateChanged(boolean screenOn) { 337 mScreenOn = screenOn; 338 } 339 340 /** 341 * Called by {@link WifiConnectivityManager} when Wi-Fi is connected. If the notification 342 * was in the connecting state, update the notification to show that it has connected to the 343 * recommended network. 344 * 345 * @param ssid The connected network's ssid 346 */ handleWifiConnected(String ssid)347 public void handleWifiConnected(String ssid) { 348 removeNetworkFromBlacklist(ssid); 349 if (mState != STATE_CONNECTING_IN_NOTIFICATION) { 350 clearPendingNotification(true /* resetRepeatTime */); 351 return; 352 } 353 354 postNotification(mNotificationBuilder.createNetworkConnectedNotification(mTag, 355 mRecommendedNetwork)); 356 357 Log.d(mTag, "User connected to recommended network: " 358 + "\"" + mRecommendedNetwork.SSID + "\""); 359 mWifiMetrics.incrementConnectToNetworkNotification(mTag, 360 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_CONNECTED_TO_NETWORK); 361 mState = STATE_CONNECTED_NOTIFICATION; 362 mHandler.postDelayed( 363 () -> { 364 if (mState == STATE_CONNECTED_NOTIFICATION) { 365 clearPendingNotification(true /* resetRepeatTime */); 366 } 367 }, 368 TIME_TO_SHOW_CONNECTED_MILLIS); 369 } 370 371 /** 372 * Handles when a Wi-Fi connection attempt failed. 373 */ handleConnectionFailure()374 public void handleConnectionFailure() { 375 if (mState != STATE_CONNECTING_IN_NOTIFICATION) { 376 return; 377 } 378 postNotification(mNotificationBuilder.createNetworkFailedNotification(mTag)); 379 380 Log.d(mTag, "User failed to connect to recommended network: " 381 + "\"" + mRecommendedNetwork.SSID + "\""); 382 mWifiMetrics.incrementConnectToNetworkNotification(mTag, 383 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_FAILED_TO_CONNECT); 384 mState = STATE_CONNECT_FAILED_NOTIFICATION; 385 mHandler.postDelayed( 386 () -> { 387 if (mState == STATE_CONNECT_FAILED_NOTIFICATION) { 388 clearPendingNotification(false /* resetRepeatTime */); 389 } 390 }, 391 TIME_TO_SHOW_FAILED_MILLIS); 392 } 393 getNotificationManager()394 private NotificationManager getNotificationManager() { 395 return (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); 396 } 397 postInitialNotification(ScanResult recommendedNetwork)398 private void postInitialNotification(ScanResult recommendedNetwork) { 399 if (mRecommendedNetwork != null 400 && TextUtils.equals(mRecommendedNetwork.SSID, recommendedNetwork.SSID)) { 401 return; 402 } 403 404 postNotification(mNotificationBuilder.createConnectToAvailableNetworkNotification(mTag, 405 recommendedNetwork)); 406 407 if (mState == STATE_NO_NOTIFICATION) { 408 mWifiMetrics.incrementConnectToNetworkNotification(mTag, 409 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_RECOMMEND_NETWORK); 410 } else { 411 mWifiMetrics.incrementNumNetworkRecommendationUpdates(mTag); 412 } 413 mState = STATE_SHOWING_RECOMMENDATION_NOTIFICATION; 414 mRecommendedNetwork = recommendedNetwork; 415 mNotificationRepeatTime = mClock.getWallClockMillis() + mNotificationRepeatDelay; 416 } 417 postNotification(Notification notification)418 private void postNotification(Notification notification) { 419 getNotificationManager().notify(mSystemMessageNotificationId, notification); 420 } 421 handleConnectToNetworkAction()422 private void handleConnectToNetworkAction() { 423 mWifiMetrics.incrementConnectToNetworkNotificationAction(mTag, mState, 424 ConnectToNetworkNotificationAndActionCount.ACTION_CONNECT_TO_NETWORK); 425 if (mState != STATE_SHOWING_RECOMMENDATION_NOTIFICATION) { 426 return; 427 } 428 postNotification(mNotificationBuilder.createNetworkConnectingNotification(mTag, 429 mRecommendedNetwork)); 430 mWifiMetrics.incrementConnectToNetworkNotification(mTag, 431 ConnectToNetworkNotificationAndActionCount.NOTIFICATION_CONNECTING_TO_NETWORK); 432 433 Log.d(mTag, 434 "User initiated connection to recommended network: " 435 + "\"" + mRecommendedNetwork.SSID + "\""); 436 WifiConfiguration network = createRecommendedNetworkConfig(mRecommendedNetwork); 437 438 NetworkUpdateResult result = mConfigManager.addOrUpdateNetwork(network, Process.WIFI_UID); 439 if (result.isSuccess()) { 440 mWifiMetrics.setNominatorForNetwork(result.netId, mNominatorId); 441 442 Message msg = Message.obtain(); 443 msg.what = WifiManager.CONNECT_NETWORK; 444 msg.arg1 = result.netId; 445 msg.obj = null; 446 msg.replyTo = mSrcMessenger; 447 mClientModeImpl.sendMessage(msg); 448 addNetworkToBlacklist(mRecommendedNetwork.SSID); 449 } 450 451 mState = STATE_CONNECTING_IN_NOTIFICATION; 452 mHandler.postDelayed( 453 () -> { 454 if (mState == STATE_CONNECTING_IN_NOTIFICATION) { 455 handleConnectionFailure(); 456 } 457 }, 458 TIME_TO_SHOW_CONNECTING_MILLIS); 459 } 460 addNetworkToBlacklist(String ssid)461 private void addNetworkToBlacklist(String ssid) { 462 mBlacklistedSsids.add(ssid); 463 mWifiMetrics.setNetworkRecommenderBlocklistSize(mTag, mBlacklistedSsids.size()); 464 mConfigManager.saveToStore(false /* forceWrite */); 465 Log.d(mTag, "Network is added to the network notification blacklist: " 466 + "\"" + ssid + "\""); 467 } 468 removeNetworkFromBlacklist(String ssid)469 private void removeNetworkFromBlacklist(String ssid) { 470 if (ssid == null) { 471 return; 472 } 473 if (!mBlacklistedSsids.remove(ssid)) { 474 return; 475 } 476 mWifiMetrics.setNetworkRecommenderBlocklistSize(mTag, mBlacklistedSsids.size()); 477 mConfigManager.saveToStore(false /* forceWrite */); 478 Log.d(mTag, "Network is removed from the network notification blacklist: " 479 + "\"" + ssid + "\""); 480 } 481 createRecommendedNetworkConfig(ScanResult recommendedNetwork)482 WifiConfiguration createRecommendedNetworkConfig(ScanResult recommendedNetwork) { 483 return ScanResultUtil.createNetworkFromScanResult(recommendedNetwork); 484 } 485 handleSeeAllNetworksAction()486 private void handleSeeAllNetworksAction() { 487 mWifiMetrics.incrementConnectToNetworkNotificationAction(mTag, mState, 488 ConnectToNetworkNotificationAndActionCount.ACTION_PICK_WIFI_NETWORK); 489 startWifiSettings(); 490 } 491 startWifiSettings()492 private void startWifiSettings() { 493 // Close notification drawer before opening the picker. 494 mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); 495 mContext.startActivity( 496 new Intent(Settings.ACTION_WIFI_SETTINGS) 497 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); 498 clearPendingNotification(false /* resetRepeatTime */); 499 } 500 handleConnectionAttemptFailedToSend()501 private void handleConnectionAttemptFailedToSend() { 502 handleConnectionFailure(); 503 mWifiMetrics.incrementNumNetworkConnectMessageFailedToSend(mTag); 504 } 505 handlePickWifiNetworkAfterConnectFailure()506 private void handlePickWifiNetworkAfterConnectFailure() { 507 mWifiMetrics.incrementConnectToNetworkNotificationAction(mTag, mState, 508 ConnectToNetworkNotificationAndActionCount 509 .ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE); 510 startWifiSettings(); 511 } 512 handleUserDismissedAction()513 private void handleUserDismissedAction() { 514 Log.d(mTag, "User dismissed notification with state=" + mState); 515 mWifiMetrics.incrementConnectToNetworkNotificationAction(mTag, mState, 516 ConnectToNetworkNotificationAndActionCount.ACTION_USER_DISMISSED_NOTIFICATION); 517 if (mState == STATE_SHOWING_RECOMMENDATION_NOTIFICATION) { 518 // blacklist dismissed network 519 addNetworkToBlacklist(mRecommendedNetwork.SSID); 520 } 521 resetStateAndDelayNotification(); 522 } 523 resetStateAndDelayNotification()524 private void resetStateAndDelayNotification() { 525 mState = STATE_NO_NOTIFICATION; 526 mNotificationRepeatTime = System.currentTimeMillis() + mNotificationRepeatDelay; 527 mRecommendedNetwork = null; 528 } 529 530 /** Dump this network notifier's state. */ dump(FileDescriptor fd, PrintWriter pw, String[] args)531 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 532 pw.println(mTag + ": "); 533 pw.println("mSettingEnabled " + mSettingEnabled); 534 pw.println("currentTime: " + mClock.getWallClockMillis()); 535 pw.println("mNotificationRepeatTime: " + mNotificationRepeatTime); 536 pw.println("mState: " + mState); 537 pw.println("mBlacklistedSsids: " + mBlacklistedSsids.toString()); 538 } 539 540 private class AvailableNetworkNotifierStoreData implements SsidSetStoreData.DataSource { 541 @Override getSsids()542 public Set<String> getSsids() { 543 return new ArraySet<>(mBlacklistedSsids); 544 } 545 546 @Override setSsids(Set<String> ssidList)547 public void setSsids(Set<String> ssidList) { 548 mBlacklistedSsids.addAll(ssidList); 549 mWifiMetrics.setNetworkRecommenderBlocklistSize(mTag, mBlacklistedSsids.size()); 550 } 551 } 552 553 private class NotificationEnabledSettingObserver extends ContentObserver { NotificationEnabledSettingObserver(Handler handler)554 NotificationEnabledSettingObserver(Handler handler) { 555 super(handler); 556 } 557 register()558 public void register() { 559 mFrameworkFacade.registerContentObserver(mContext, 560 Settings.Global.getUriFor(mToggleSettingsName), true, this); 561 mSettingEnabled = getValue(); 562 } 563 564 @Override onChange(boolean selfChange)565 public void onChange(boolean selfChange) { 566 super.onChange(selfChange); 567 mSettingEnabled = getValue(); 568 clearPendingNotification(true /* resetRepeatTime */); 569 } 570 getValue()571 private boolean getValue() { 572 boolean enabled = 573 mFrameworkFacade.getIntegerSetting(mContext, mToggleSettingsName, 1) == 1; 574 mWifiMetrics.setIsWifiNetworksAvailableNotificationEnabled(mTag, enabled); 575 Log.d(mTag, "Settings toggle enabled=" + enabled); 576 return enabled; 577 } 578 } 579 } 580