diff options
author | Stephen Chen <stewchen@google.com> | 2017-08-08 17:55:21 -0700 |
---|---|---|
committer | Stephen Chen <stewchen@google.com> | 2017-09-05 11:40:23 -0700 |
commit | b280c399d7be7d04a245c5fc2d2897f0ddc9cc0a (patch) | |
tree | 7af445cadaed0b7bd6bfbb3584c18011d6534456 /service | |
parent | 69fa2e7fa12b8f4c24a27b3291a0744cd808a324 (diff) |
ONA: Implement SSID blacklist handling for dismissed networks.
When ONA notifications are dismissed by the user, the recommended
network ssid is permanently blacklisted.
This change also removes the use of currentRecommendation in the
recommendation logic, because the extra stickiness is not neccesary due
to the slow scan rate that triggers a recommendation update.
Bug: 64091575
Bug: 37357441
Test: frameworks/opt/net/wifi/tests/wifitests/runtests.sh
Change-Id: I27fc667ae51f9dbc4665ba9d15b18ed3e6daa058
Diffstat (limited to 'service')
4 files changed, 183 insertions, 17 deletions
diff --git a/service/java/com/android/server/wifi/OpenNetworkNotifier.java b/service/java/com/android/server/wifi/OpenNetworkNotifier.java index fc144c139..692c8e22c 100644 --- a/service/java/com/android/server/wifi/OpenNetworkNotifier.java +++ b/service/java/com/android/server/wifi/OpenNetworkNotifier.java @@ -29,6 +29,8 @@ import android.os.Looper; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.util.ArraySet; +import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; @@ -36,18 +38,25 @@ import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.List; +import java.util.Set; /** * Takes care of handling the "open wi-fi network available" notification + * + * NOTE: These API's are not thread safe and should only be used from WifiStateMachine thread. * @hide */ public class OpenNetworkNotifier { + private static final String TAG = "OpenNetworkNotifier"; + static final String ACTION_USER_DISMISSED_NOTIFICATION = "com.android.server.wifi.OpenNetworkNotifier.USER_DISMISSED_NOTIFICATION"; static final String ACTION_USER_TAPPED_CONTENT = "com.android.server.wifi.OpenNetworkNotifier.USER_TAPPED_CONTENT"; + /** Identifier of the {@link SsidSetStoreData}. */ + private static final String STORE_DATA_IDENTIFIER = "OpenNetworkNotifierBlacklist"; /** * The {@link Clock#getWallClockMillis()} must be at least this value for us * to show the notification again. @@ -68,10 +77,14 @@ public class OpenNetworkNotifier { /** Whether the screen is on or not. */ private boolean mScreenOn; + /** List of SSIDs blacklisted from recommendation. */ + private final Set<String> mBlacklistedSsids; + private final Context mContext; private final Handler mHandler; private final FrameworkFacade mFrameworkFacade; private final Clock mClock; + private final WifiConfigManager mConfigManager; private final OpenNetworkRecommender mOpenNetworkRecommender; private final OpenNetworkNotificationBuilder mOpenNetworkNotificationBuilder; @@ -82,15 +95,22 @@ public class OpenNetworkNotifier { Looper looper, FrameworkFacade framework, Clock clock, + WifiConfigManager wifiConfigManager, + WifiConfigStore wifiConfigStore, OpenNetworkRecommender openNetworkRecommender) { mContext = context; mHandler = new Handler(looper); mFrameworkFacade = framework; mClock = clock; + mConfigManager = wifiConfigManager; mOpenNetworkRecommender = openNetworkRecommender; mOpenNetworkNotificationBuilder = new OpenNetworkNotificationBuilder(context, framework); mScreenOn = false; + mBlacklistedSsids = new ArraySet<>(); + wifiConfigStore.registerStoreData(new SsidSetStoreData( + STORE_DATA_IDENTIFIER, new OpenNetworkNotifierStoreData())); + // Setting is in seconds mNotificationRepeatDelay = mFrameworkFacade.getIntegerSetting(context, Settings.Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, @@ -165,7 +185,7 @@ public class OpenNetworkNotifier { } mRecommendedNetwork = mOpenNetworkRecommender.recommendNetwork( - availableNetworks, mRecommendedNetwork); + availableNetworks, new ArraySet<>(mBlacklistedSsids)); postNotification(availableNetworks.size()); } @@ -201,8 +221,14 @@ public class OpenNetworkNotifier { .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); } - /** A delay is set before the next shown notification after user dismissal. */ private void handleUserDismissedAction() { + if (mRecommendedNetwork != null) { + // blacklist dismissed network + mBlacklistedSsids.add(mRecommendedNetwork.SSID); + mConfigManager.saveToStore(false /* forceWrite */); + Log.d(TAG, "Network is added to the open network notification blacklist: " + + mRecommendedNetwork.SSID); + } mNotificationShown = false; } @@ -213,6 +239,19 @@ public class OpenNetworkNotifier { pw.println("currentTime: " + mClock.getWallClockMillis()); pw.println("mNotificationRepeatTime: " + mNotificationRepeatTime); pw.println("mNotificationShown: " + mNotificationShown); + pw.println("mBlacklistedSsids: " + mBlacklistedSsids.toString()); + } + + private class OpenNetworkNotifierStoreData implements SsidSetStoreData.DataSource { + @Override + public Set<String> getSsids() { + return new ArraySet<>(mBlacklistedSsids); + } + + @Override + public void setSsids(Set<String> ssidList) { + mBlacklistedSsids.addAll(ssidList); + } } private class NotificationEnabledSettingObserver extends ContentObserver { diff --git a/service/java/com/android/server/wifi/OpenNetworkRecommender.java b/service/java/com/android/server/wifi/OpenNetworkRecommender.java index cd460e58b..5ceeddded 100644 --- a/service/java/com/android/server/wifi/OpenNetworkRecommender.java +++ b/service/java/com/android/server/wifi/OpenNetworkRecommender.java @@ -20,9 +20,12 @@ import android.annotation.NonNull; import android.net.wifi.ScanResult; import java.util.List; +import java.util.Set; /** * Helps recommend the best available network for {@link OpenNetworkNotifier}. + * + * NOTE: These API's are not thread safe and should only be used from WifiStateMachine thread. * @hide */ public class OpenNetworkRecommender { @@ -32,31 +35,24 @@ public class OpenNetworkRecommender { * * @param networks List of scan details to pick a recommendation. This list should not be null * or empty. - * @param currentRecommendation The currently recommended network. + * @param blacklistedSsids The list of SSIDs that should not be recommended. */ - public ScanResult recommendNetwork( - @NonNull List<ScanDetail> networks, ScanResult currentRecommendation) { - ScanResult currentUpdatedRecommendation = null; + public ScanResult recommendNetwork(@NonNull List<ScanDetail> networks, + @NonNull Set<String> blacklistedSsids) { ScanResult result = null; int highestRssi = Integer.MIN_VALUE; for (ScanDetail scanDetail : networks) { ScanResult scanResult = scanDetail.getScanResult(); - if (currentRecommendation != null - && currentRecommendation.SSID.equals(scanResult.SSID)) { - currentUpdatedRecommendation = scanResult; - } - if (scanResult.level > highestRssi) { result = scanResult; highestRssi = scanResult.level; } } - if (currentUpdatedRecommendation != null - && currentUpdatedRecommendation.level >= result.level) { - return currentUpdatedRecommendation; - } else { - return result; + + if (result != null && blacklistedSsids.contains(result.SSID)) { + result = null; } + return result; } } diff --git a/service/java/com/android/server/wifi/SsidSetStoreData.java b/service/java/com/android/server/wifi/SsidSetStoreData.java new file mode 100644 index 000000000..daed26a6a --- /dev/null +++ b/service/java/com/android/server/wifi/SsidSetStoreData.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wifi; + +import android.text.TextUtils; + +import com.android.server.wifi.util.XmlUtil; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +/** + * Store data for network notifiers. + * + * Below are the current configuration data for each respective store file: + * + * Share Store (system wide configurations) + * - No data + * + * User Store (user specific configurations) + * - Set of blacklisted SSIDs + */ +public class SsidSetStoreData implements WifiConfigStore.StoreData { + private static final String XML_TAG_SECTION_HEADER_SUFFIX = "ConfigData"; + private static final String XML_TAG_SSID_SET = "SSIDSet"; + + private final String mTagName; + private final DataSource mDataSource; + + /** + * Interface define the data source for the notifier store data. + */ + public interface DataSource { + /** + * Retrieve the SSID set from the data source. + * + * @return Set of SSIDs + */ + Set<String> getSsids(); + + /** + * Update the SSID set in the data source. + * + * @param ssidSet The set of SSIDs + */ + void setSsids(Set<String> ssidSet); + } + + /** + * Creates the SSID Set store data. + * + * @param name Identifier of the SSID set. + * @param dataSource The DataSource that implements the update and retrieval of the SSID set. + */ + SsidSetStoreData(String name, DataSource dataSource) { + mTagName = name + XML_TAG_SECTION_HEADER_SUFFIX; + mDataSource = dataSource; + } + + @Override + public void serializeData(XmlSerializer out, boolean shared) + throws XmlPullParserException, IOException { + if (shared) { + throw new XmlPullParserException("Share data not supported"); + } + Set<String> ssidSet = mDataSource.getSsids(); + if (ssidSet != null && !ssidSet.isEmpty()) { + XmlUtil.writeNextValue(out, XML_TAG_SSID_SET, mDataSource.getSsids()); + } + } + + @Override + public void deserializeData(XmlPullParser in, int outerTagDepth, boolean shared) + throws XmlPullParserException, IOException { + if (shared) { + throw new XmlPullParserException("Share data not supported"); + } + + while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { + String[] valueName = new String[1]; + Object value = XmlUtil.readCurrentValue(in, valueName); + if (TextUtils.isEmpty(valueName[0])) { + throw new XmlPullParserException("Missing value name"); + } + switch (valueName[0]) { + case XML_TAG_SSID_SET: + mDataSource.setSsids((Set<String>) value); + break; + default: + throw new XmlPullParserException("Unknown tag under " + + mTagName + ": " + valueName[0]); + } + } + } + + @Override + public void resetData(boolean shared) { + if (!shared) { + mDataSource.setSsids(new HashSet<>()); + } + } + + @Override + public String getName() { + return mTagName; + } + + @Override + public boolean supportShareData() { + return false; + } +} diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java index 60c5d2fb9..26d702477 100644 --- a/service/java/com/android/server/wifi/WifiInjector.java +++ b/service/java/com/android/server/wifi/WifiInjector.java @@ -233,7 +233,7 @@ public class WifiInjector { mCertManager = new WifiCertManager(mContext); mOpenNetworkNotifier = new OpenNetworkNotifier(mContext, mWifiStateMachineHandlerThread.getLooper(), mFrameworkFacade, mClock, - new OpenNetworkRecommender()); + mWifiConfigManager, mWifiConfigStore, new OpenNetworkRecommender()); mLockManager = new WifiLockManager(mContext, BatteryStatsService.getService()); mWifiController = new WifiController(mContext, mWifiStateMachine, mSettingsStore, mLockManager, mWifiServiceHandlerThread.getLooper(), mFrameworkFacade); |