1a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach/* 2a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach * Copyright 2017 The Android Open Source Project 3a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach * 4a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach * Licensed under the Apache License, Version 2.0 (the "License"); 5a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach * you may not use this file except in compliance with the License. 6a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach * You may obtain a copy of the License at 7a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach * 8a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach * http://www.apache.org/licenses/LICENSE-2.0 9a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach * 10a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach * Unless required by applicable law or agreed to in writing, software 11a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach * distributed under the License is distributed on an "AS IS" BASIS, 12a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach * See the License for the specific language governing permissions and 14a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach * limitations under the License. 15a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach */ 16a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach 17a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbachpackage com.android.server.wifi; 18a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach 1917139823e3dbbcdb46f1e586427297d72a5a0e66Eric Schwarzenbachimport static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED; 2017139823e3dbbcdb46f1e586427297d72a5a0e66Eric Schwarzenbach 21a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbachimport android.content.Context; 22a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbachimport android.database.ContentObserver; 23115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbachimport android.net.wifi.ScanResult; 24115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbachimport android.net.wifi.WifiConfiguration; 25115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbachimport android.net.wifi.WifiScanner; 26a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbachimport android.os.Handler; 27a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbachimport android.os.Looper; 28a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbachimport android.provider.Settings; 29115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbachimport android.util.Log; 30a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach 31a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbachimport com.android.internal.annotations.VisibleForTesting; 32a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach 3304263765dc4bb2a74722d69db56c5b42e7fb1bc9Eric Schwarzenbachimport java.io.FileDescriptor; 3404263765dc4bb2a74722d69db56c5b42e7fb1bc9Eric Schwarzenbachimport java.io.PrintWriter; 35b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbachimport java.util.Arrays; 36b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbachimport java.util.Collection; 37115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbachimport java.util.HashSet; 38115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbachimport java.util.List; 39115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbachimport java.util.Set; 404f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbachimport java.util.stream.Collectors; 41115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach 4204263765dc4bb2a74722d69db56c5b42e7fb1bc9Eric Schwarzenbach 43a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach/** 44a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach * WakeupController is responsible managing Auto Wifi. 45a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach * 46a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach * <p>It determines if and when to re-enable wifi after it has been turned off by the user. 47a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach */ 48a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbachpublic class WakeupController { 49a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach 50115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach private static final String TAG = "WakeupController"; 51115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach 5232152cdeeefb4d8cc9a1137232892e5360ae1f5bEric Schwarzenbach private static final boolean USE_PLATFORM_WIFI_WAKE = true; 53a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach 54a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach private final Context mContext; 55a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach private final Handler mHandler; 56a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach private final FrameworkFacade mFrameworkFacade; 57a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach private final ContentObserver mContentObserver; 58a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach private final WakeupLock mWakeupLock; 59b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach private final WakeupEvaluator mWakeupEvaluator; 609d60c0ff94757e8862f167f6de54789fe2e1bab2Eric Schwarzenbach private final WakeupOnboarding mWakeupOnboarding; 61a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach private final WifiConfigManager mWifiConfigManager; 62115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach private final WifiInjector mWifiInjector; 63aa872c243eb5b27beaefe1360b69a46ceb016b56Eric Schwarzenbach private final WakeupConfigStoreData mWakeupConfigStoreData; 6412d31e7fea8e5c17dddc0ab433c26c31a3bf2550Eric Schwarzenbach private final WifiWakeMetrics mWifiWakeMetrics; 65115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach 66115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach private final WifiScanner.ScanListener mScanListener = new WifiScanner.ScanListener() { 67115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach @Override 68115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach public void onPeriodChanged(int periodInMs) { 69115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach // no-op 70115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach } 71115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach 72115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach @Override 73115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach public void onResults(WifiScanner.ScanData[] results) { 74b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach if (results.length == 1 && results[0].isAllChannelsScanned()) { 75f18cd43a78de639b3680a0e881d90d02ae57decdEric Schwarzenbach handleScanResults(filterDfsScanResults(Arrays.asList(results[0].getResults()))); 76b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach } 77115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach } 78115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach 79115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach @Override 80115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach public void onFullResult(ScanResult fullScanResult) { 81115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach // no-op 82115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach } 83115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach 84115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach @Override 85115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach public void onSuccess() { 86115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach // no-op 87115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach } 88115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach 89115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach @Override 90115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach public void onFailure(int reason, String description) { 91115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach Log.e(TAG, "ScanListener onFailure: " + reason + ": " + description); 92115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach } 93115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach }; 94a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach 95a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach /** Whether this feature is enabled in Settings. */ 96a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach private boolean mWifiWakeupEnabled; 97a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach 98a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach /** Whether the WakeupController is currently active. */ 99a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach private boolean mIsActive = false; 100a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach 10112d31e7fea8e5c17dddc0ab433c26c31a3bf2550Eric Schwarzenbach /** The number of scans that have been handled by the controller since last {@link #reset()}. */ 10212d31e7fea8e5c17dddc0ab433c26c31a3bf2550Eric Schwarzenbach private int mNumScansHandled = 0; 10312d31e7fea8e5c17dddc0ab433c26c31a3bf2550Eric Schwarzenbach 104eaa590a3216ed7bf971c67a43ae68ed6e3ad1ce1Eric Schwarzenbach /** Whether Wifi verbose logging is enabled. */ 105eaa590a3216ed7bf971c67a43ae68ed6e3ad1ce1Eric Schwarzenbach private boolean mVerboseLoggingEnabled; 106eaa590a3216ed7bf971c67a43ae68ed6e3ad1ce1Eric Schwarzenbach 107a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach public WakeupController( 108a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach Context context, 109a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach Looper looper, 110a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach WakeupLock wakeupLock, 111b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach WakeupEvaluator wakeupEvaluator, 1129d60c0ff94757e8862f167f6de54789fe2e1bab2Eric Schwarzenbach WakeupOnboarding wakeupOnboarding, 113a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach WifiConfigManager wifiConfigManager, 114a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach WifiConfigStore wifiConfigStore, 11512d31e7fea8e5c17dddc0ab433c26c31a3bf2550Eric Schwarzenbach WifiWakeMetrics wifiWakeMetrics, 116115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach WifiInjector wifiInjector, 117a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach FrameworkFacade frameworkFacade) { 118a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach mContext = context; 119a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach mHandler = new Handler(looper); 120a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach mWakeupLock = wakeupLock; 121b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach mWakeupEvaluator = wakeupEvaluator; 1229d60c0ff94757e8862f167f6de54789fe2e1bab2Eric Schwarzenbach mWakeupOnboarding = wakeupOnboarding; 123a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach mWifiConfigManager = wifiConfigManager; 12412d31e7fea8e5c17dddc0ab433c26c31a3bf2550Eric Schwarzenbach mWifiWakeMetrics = wifiWakeMetrics; 125a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach mFrameworkFacade = frameworkFacade; 126115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach mWifiInjector = wifiInjector; 127a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach mContentObserver = new ContentObserver(mHandler) { 128a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach @Override 129a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach public void onChange(boolean selfChange) { 1305aad8ece7e38a80db917d49b5245f6b8c6dca273Eric Schwarzenbach readWifiWakeupEnabledFromSettings(); 1315aad8ece7e38a80db917d49b5245f6b8c6dca273Eric Schwarzenbach mWakeupOnboarding.setOnboarded(); 132a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach } 133a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach }; 134a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach mFrameworkFacade.registerContentObserver(mContext, Settings.Global.getUriFor( 135a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach Settings.Global.WIFI_WAKEUP_ENABLED), true, mContentObserver); 1365aad8ece7e38a80db917d49b5245f6b8c6dca273Eric Schwarzenbach readWifiWakeupEnabledFromSettings(); 137a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach 138a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach // registering the store data here has the effect of reading the persisted value of the 139a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach // data sources after system boot finishes 140aa872c243eb5b27beaefe1360b69a46ceb016b56Eric Schwarzenbach mWakeupConfigStoreData = new WakeupConfigStoreData( 1419d60c0ff94757e8862f167f6de54789fe2e1bab2Eric Schwarzenbach new IsActiveDataSource(), 1425aad8ece7e38a80db917d49b5245f6b8c6dca273Eric Schwarzenbach mWakeupOnboarding.getIsOnboadedDataSource(), 1435aad8ece7e38a80db917d49b5245f6b8c6dca273Eric Schwarzenbach mWakeupOnboarding.getNotificationsDataSource(), 1449d60c0ff94757e8862f167f6de54789fe2e1bab2Eric Schwarzenbach mWakeupLock.getDataSource()); 145aa872c243eb5b27beaefe1360b69a46ceb016b56Eric Schwarzenbach wifiConfigStore.registerStoreData(mWakeupConfigStoreData); 146a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach } 147a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach 1485aad8ece7e38a80db917d49b5245f6b8c6dca273Eric Schwarzenbach private void readWifiWakeupEnabledFromSettings() { 1495aad8ece7e38a80db917d49b5245f6b8c6dca273Eric Schwarzenbach mWifiWakeupEnabled = mFrameworkFacade.getIntegerSetting( 1505aad8ece7e38a80db917d49b5245f6b8c6dca273Eric Schwarzenbach mContext, Settings.Global.WIFI_WAKEUP_ENABLED, 0) == 1; 1515aad8ece7e38a80db917d49b5245f6b8c6dca273Eric Schwarzenbach Log.d(TAG, "WifiWake " + (mWifiWakeupEnabled ? "enabled" : "disabled")); 1525aad8ece7e38a80db917d49b5245f6b8c6dca273Eric Schwarzenbach } 1535aad8ece7e38a80db917d49b5245f6b8c6dca273Eric Schwarzenbach 154a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach private void setActive(boolean isActive) { 155a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach if (mIsActive != isActive) { 156b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach Log.d(TAG, "Setting active to " + isActive); 157a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach mIsActive = isActive; 158a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach mWifiConfigManager.saveToStore(false /* forceWrite */); 159a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach } 160a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach } 161a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach 162a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach /** 163115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach * Starts listening for incoming scans. 164115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach * 165115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach * <p>Should only be called upon entering ScanMode. WakeupController registers its listener with 166115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach * the WifiScanner. If the WakeupController is already active, then it returns early. Otherwise 167115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach * it performs its initialization steps and sets {@link #mIsActive} to true. 168115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach */ 169115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach public void start() { 170b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach Log.d(TAG, "start()"); 171115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach mWifiInjector.getWifiScanner().registerScanListener(mScanListener); 172115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach 173dca47232ea69a4501318b4dfb69db69e1216694fEric Schwarzenbach // If already active, we don't want to restart the session, so return early. 174115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach if (mIsActive) { 175dca47232ea69a4501318b4dfb69db69e1216694fEric Schwarzenbach mWifiWakeMetrics.recordIgnoredStart(); 176115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach return; 177115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach } 178115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach setActive(true); 179115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach 180aa872c243eb5b27beaefe1360b69a46ceb016b56Eric Schwarzenbach // ensure feature is enabled and store data has been read before performing work 181b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach if (isEnabled()) { 1829d60c0ff94757e8862f167f6de54789fe2e1bab2Eric Schwarzenbach mWakeupOnboarding.maybeShowNotification(); 18312d31e7fea8e5c17dddc0ab433c26c31a3bf2550Eric Schwarzenbach 184f18cd43a78de639b3680a0e881d90d02ae57decdEric Schwarzenbach List<ScanResult> scanResults = 185f18cd43a78de639b3680a0e881d90d02ae57decdEric Schwarzenbach filterDfsScanResults(mWifiInjector.getWifiScanner().getSingleScanResults()); 186f18cd43a78de639b3680a0e881d90d02ae57decdEric Schwarzenbach Set<ScanResultMatchInfo> matchInfos = toMatchInfos(scanResults); 187f18cd43a78de639b3680a0e881d90d02ae57decdEric Schwarzenbach matchInfos.retainAll(getGoodSavedNetworks()); 188f18cd43a78de639b3680a0e881d90d02ae57decdEric Schwarzenbach 189eaa590a3216ed7bf971c67a43ae68ed6e3ad1ce1Eric Schwarzenbach if (mVerboseLoggingEnabled) { 190f18cd43a78de639b3680a0e881d90d02ae57decdEric Schwarzenbach Log.d(TAG, "Saved networks in most recent scan:" + matchInfos); 191eaa590a3216ed7bf971c67a43ae68ed6e3ad1ce1Eric Schwarzenbach } 192eaa590a3216ed7bf971c67a43ae68ed6e3ad1ce1Eric Schwarzenbach 193f18cd43a78de639b3680a0e881d90d02ae57decdEric Schwarzenbach mWifiWakeMetrics.recordStartEvent(matchInfos.size()); 194f18cd43a78de639b3680a0e881d90d02ae57decdEric Schwarzenbach mWakeupLock.setLock(matchInfos); 1954f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach // TODO(b/77291248): request low latency scan here 196115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach } 197115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach } 1985aad8ece7e38a80db917d49b5245f6b8c6dca273Eric Schwarzenbach 199115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach /** 200115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach * Stops listening for scans. 201115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach * 202115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach * <p>Should only be called upon leaving ScanMode. It deregisters the listener from 203115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach * WifiScanner. 204115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach */ 205115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach public void stop() { 206b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach Log.d(TAG, "stop()"); 207115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach mWifiInjector.getWifiScanner().deregisterScanListener(mScanListener); 2089d60c0ff94757e8862f167f6de54789fe2e1bab2Eric Schwarzenbach mWakeupOnboarding.onStop(); 209115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach } 210115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach 211115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach /** Resets the WakeupController, setting {@link #mIsActive} to false. */ 212115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach public void reset() { 213b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach Log.d(TAG, "reset()"); 21412d31e7fea8e5c17dddc0ab433c26c31a3bf2550Eric Schwarzenbach mWifiWakeMetrics.recordResetEvent(mNumScansHandled); 21512d31e7fea8e5c17dddc0ab433c26c31a3bf2550Eric Schwarzenbach mNumScansHandled = 0; 216115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach setActive(false); 217115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach } 218115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach 219eaa590a3216ed7bf971c67a43ae68ed6e3ad1ce1Eric Schwarzenbach /** Sets verbose logging flag based on verbose level. */ 220eaa590a3216ed7bf971c67a43ae68ed6e3ad1ce1Eric Schwarzenbach public void enableVerboseLogging(int verbose) { 221eaa590a3216ed7bf971c67a43ae68ed6e3ad1ce1Eric Schwarzenbach mVerboseLoggingEnabled = verbose > 0; 222eaa590a3216ed7bf971c67a43ae68ed6e3ad1ce1Eric Schwarzenbach mWakeupLock.enableVerboseLogging(mVerboseLoggingEnabled); 223eaa590a3216ed7bf971c67a43ae68ed6e3ad1ce1Eric Schwarzenbach } 224eaa590a3216ed7bf971c67a43ae68ed6e3ad1ce1Eric Schwarzenbach 225f18cd43a78de639b3680a0e881d90d02ae57decdEric Schwarzenbach /** Returns a list of ScanResults with DFS channels removed. */ 226f18cd43a78de639b3680a0e881d90d02ae57decdEric Schwarzenbach private List<ScanResult> filterDfsScanResults(Collection<ScanResult> scanResults) { 2274f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach int[] dfsChannels = mWifiInjector.getWifiNative() 2284f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach .getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY); 2294f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach if (dfsChannels == null) { 2304f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach dfsChannels = new int[0]; 231115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach } 232115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach 2334f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach final Set<Integer> dfsChannelSet = Arrays.stream(dfsChannels).boxed() 2344f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach .collect(Collectors.toSet()); 2354f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach 2364f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach return scanResults.stream() 2374f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach .filter(scanResult -> !dfsChannelSet.contains(scanResult.frequency)) 238f18cd43a78de639b3680a0e881d90d02ae57decdEric Schwarzenbach .collect(Collectors.toList()); 239115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach } 240115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach 241f18cd43a78de639b3680a0e881d90d02ae57decdEric Schwarzenbach /** Returns a filtered set of saved networks from WifiConfigManager. */ 242115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach private Set<ScanResultMatchInfo> getGoodSavedNetworks() { 243115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach List<WifiConfiguration> savedNetworks = mWifiConfigManager.getSavedNetworks(); 244115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach 245115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach Set<ScanResultMatchInfo> goodSavedNetworks = new HashSet<>(savedNetworks.size()); 246115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach for (WifiConfiguration config : savedNetworks) { 247115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach if (isWideAreaNetwork(config) 248115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach || config.hasNoInternetAccess() 249115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach || config.noInternetAccessExpected 250115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach || !config.getNetworkSelectionStatus().getHasEverConnected()) { 251115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach continue; 252115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach } 253115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach goodSavedNetworks.add(ScanResultMatchInfo.fromWifiConfiguration(config)); 254115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach } 255115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach 256115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach return goodSavedNetworks; 257115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach } 258115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach 259115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach //TODO(b/69271702) implement WAN filtering 2604f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach private static boolean isWideAreaNetwork(WifiConfiguration config) { 261115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach return false; 262115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach } 263115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach 264115c8923f9cfee8052c03eb5c92359d4156a86b2Eric Schwarzenbach /** 265b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach * Handles incoming scan results. 266b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach * 2674f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach * <p>The controller updates the WakeupLock with the incoming scan results. If WakeupLock is not 2684f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach * yet fully initialized, it adds the current scanResults to the lock and returns. If WakeupLock 2694f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach * is initialized but not empty, the controller updates the lock with the current scan. If it is 2704f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach * both initialized and empty, it evaluates scan results for a match with saved networks. If a 2714f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach * match exists, it enables wifi. 272a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach * 273aa872c243eb5b27beaefe1360b69a46ceb016b56Eric Schwarzenbach * <p>The feature must be enabled and the store data must be loaded in order for the controller 274aa872c243eb5b27beaefe1360b69a46ceb016b56Eric Schwarzenbach * to handle scan results. 275aa872c243eb5b27beaefe1360b69a46ceb016b56Eric Schwarzenbach * 276b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach * @param scanResults The scan results with which to update the controller 277a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach */ 278b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach private void handleScanResults(Collection<ScanResult> scanResults) { 279b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach if (!isEnabled()) { 280eaa590a3216ed7bf971c67a43ae68ed6e3ad1ce1Eric Schwarzenbach Log.d(TAG, "Attempted to handleScanResults while not enabled"); 281b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach return; 282b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach } 283b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach 2845aad8ece7e38a80db917d49b5245f6b8c6dca273Eric Schwarzenbach // only count scan as handled if isEnabled 2854f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach mNumScansHandled++; 2864f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach if (mVerboseLoggingEnabled) { 2874f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach Log.d(TAG, "Incoming scan #" + mNumScansHandled); 2884f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach } 289b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach 2905aad8ece7e38a80db917d49b5245f6b8c6dca273Eric Schwarzenbach // need to show notification here in case user turns phone on while wifi is off 2915aad8ece7e38a80db917d49b5245f6b8c6dca273Eric Schwarzenbach mWakeupOnboarding.maybeShowNotification(); 2925aad8ece7e38a80db917d49b5245f6b8c6dca273Eric Schwarzenbach 293f18cd43a78de639b3680a0e881d90d02ae57decdEric Schwarzenbach // filter out unsaved networks 294f18cd43a78de639b3680a0e881d90d02ae57decdEric Schwarzenbach Set<ScanResultMatchInfo> goodSavedNetworks = getGoodSavedNetworks(); 295f18cd43a78de639b3680a0e881d90d02ae57decdEric Schwarzenbach Set<ScanResultMatchInfo> matchInfos = toMatchInfos(scanResults); 296f18cd43a78de639b3680a0e881d90d02ae57decdEric Schwarzenbach matchInfos.retainAll(goodSavedNetworks); 2975aad8ece7e38a80db917d49b5245f6b8c6dca273Eric Schwarzenbach 298f18cd43a78de639b3680a0e881d90d02ae57decdEric Schwarzenbach mWakeupLock.update(matchInfos); 2994f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach if (!mWakeupLock.isUnlocked()) { 3004f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach return; 301b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach } 302b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach 303f18cd43a78de639b3680a0e881d90d02ae57decdEric Schwarzenbach ScanResult network = mWakeupEvaluator.findViableNetwork(scanResults, goodSavedNetworks); 304b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach 305b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach if (network != null) { 306eaa590a3216ed7bf971c67a43ae68ed6e3ad1ce1Eric Schwarzenbach Log.d(TAG, "Enabling wifi for network: " + network.SSID); 30717139823e3dbbcdb46f1e586427297d72a5a0e66Eric Schwarzenbach enableWifi(); 308b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach } 309b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach } 310b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach 31117139823e3dbbcdb46f1e586427297d72a5a0e66Eric Schwarzenbach /** 3124f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach * Converts ScanResults to ScanResultMatchInfos. 3134f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach */ 3144f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach private static Set<ScanResultMatchInfo> toMatchInfos(Collection<ScanResult> scanResults) { 3154f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach return scanResults.stream() 3164f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach .map(ScanResultMatchInfo::fromScanResult) 3174f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach .collect(Collectors.toSet()); 3184f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach } 3194f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach 3204f894bd0f4b378972d10f64390ab710da54d5cc6Eric Schwarzenbach /** 32117139823e3dbbcdb46f1e586427297d72a5a0e66Eric Schwarzenbach * Enables wifi. 32217139823e3dbbcdb46f1e586427297d72a5a0e66Eric Schwarzenbach * 32317139823e3dbbcdb46f1e586427297d72a5a0e66Eric Schwarzenbach * <p>This method ignores all checks and assumes that {@link WifiStateMachine} is currently 32417139823e3dbbcdb46f1e586427297d72a5a0e66Eric Schwarzenbach * in ScanModeState. 32517139823e3dbbcdb46f1e586427297d72a5a0e66Eric Schwarzenbach */ 32617139823e3dbbcdb46f1e586427297d72a5a0e66Eric Schwarzenbach private void enableWifi() { 327eaa590a3216ed7bf971c67a43ae68ed6e3ad1ce1Eric Schwarzenbach if (USE_PLATFORM_WIFI_WAKE) { 328eaa590a3216ed7bf971c67a43ae68ed6e3ad1ce1Eric Schwarzenbach // TODO(b/72180295): ensure that there is no race condition with WifiServiceImpl here 329eaa590a3216ed7bf971c67a43ae68ed6e3ad1ce1Eric Schwarzenbach if (mWifiInjector.getWifiSettingsStore().handleWifiToggled(true /* wifiEnabled */)) { 330eaa590a3216ed7bf971c67a43ae68ed6e3ad1ce1Eric Schwarzenbach mWifiInjector.getWifiController().sendMessage(CMD_WIFI_TOGGLED); 331eaa590a3216ed7bf971c67a43ae68ed6e3ad1ce1Eric Schwarzenbach mWifiWakeMetrics.recordWakeupEvent(mNumScansHandled); 332eaa590a3216ed7bf971c67a43ae68ed6e3ad1ce1Eric Schwarzenbach } 333b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach } 334b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach } 335b6b9c915c200d71da56026d8c3aeec9c243a933aEric Schwarzenbach 336aa872c243eb5b27beaefe1360b69a46ceb016b56Eric Schwarzenbach /** 337aa872c243eb5b27beaefe1360b69a46ceb016b56Eric Schwarzenbach * Whether the feature is currently enabled. 338aa872c243eb5b27beaefe1360b69a46ceb016b56Eric Schwarzenbach * 339aa872c243eb5b27beaefe1360b69a46ceb016b56Eric Schwarzenbach * <p>This method checks both the Settings value and the store data to ensure that it has been 340aa872c243eb5b27beaefe1360b69a46ceb016b56Eric Schwarzenbach * read. 341aa872c243eb5b27beaefe1360b69a46ceb016b56Eric Schwarzenbach */ 342a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach @VisibleForTesting 343a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach boolean isEnabled() { 344aa872c243eb5b27beaefe1360b69a46ceb016b56Eric Schwarzenbach return mWifiWakeupEnabled && mWakeupConfigStoreData.hasBeenRead(); 345a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach } 346a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach 34704263765dc4bb2a74722d69db56c5b42e7fb1bc9Eric Schwarzenbach /** Dumps wakeup controller state. */ 34804263765dc4bb2a74722d69db56c5b42e7fb1bc9Eric Schwarzenbach public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 34904263765dc4bb2a74722d69db56c5b42e7fb1bc9Eric Schwarzenbach pw.println("Dump of WakeupController"); 35004263765dc4bb2a74722d69db56c5b42e7fb1bc9Eric Schwarzenbach pw.println("USE_PLATFORM_WIFI_WAKE: " + USE_PLATFORM_WIFI_WAKE); 35112d31e7fea8e5c17dddc0ab433c26c31a3bf2550Eric Schwarzenbach pw.println("mWifiWakeupEnabled: " + mWifiWakeupEnabled); 35212d31e7fea8e5c17dddc0ab433c26c31a3bf2550Eric Schwarzenbach pw.println("isOnboarded: " + mWakeupOnboarding.isOnboarded()); 35312d31e7fea8e5c17dddc0ab433c26c31a3bf2550Eric Schwarzenbach pw.println("configStore hasBeenRead: " + mWakeupConfigStoreData.hasBeenRead()); 35404263765dc4bb2a74722d69db56c5b42e7fb1bc9Eric Schwarzenbach pw.println("mIsActive: " + mIsActive); 35512d31e7fea8e5c17dddc0ab433c26c31a3bf2550Eric Schwarzenbach pw.println("mNumScansHandled: " + mNumScansHandled); 35612d31e7fea8e5c17dddc0ab433c26c31a3bf2550Eric Schwarzenbach 35704263765dc4bb2a74722d69db56c5b42e7fb1bc9Eric Schwarzenbach mWakeupLock.dump(fd, pw, args); 35804263765dc4bb2a74722d69db56c5b42e7fb1bc9Eric Schwarzenbach } 35904263765dc4bb2a74722d69db56c5b42e7fb1bc9Eric Schwarzenbach 360a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach private class IsActiveDataSource implements WakeupConfigStoreData.DataSource<Boolean> { 361a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach 362a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach @Override 363a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach public Boolean getData() { 364a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach return mIsActive; 365a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach } 366a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach 367a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach @Override 368a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach public void setData(Boolean data) { 369a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach mIsActive = data; 370a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach } 371a57806da53f2eadcf12475892ae3a0e0e58d98cdEric Schwarzenbach } 372a55e8d795bba5aa66f692cffa8fa28e3b4174546Eric Schwarzenbach} 373