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