summaryrefslogtreecommitdiffstats
path: root/service/java/com
diff options
context:
space:
mode:
authorRoshan Pius <rpius@google.com>2019-01-16 16:24:02 -0800
committerRoshan Pius <rpius@google.com>2019-01-18 08:02:25 -0800
commite9b9e8526f976a8942711d546547de6b8c286220 (patch)
tree568a2a0825f3ace8ea91104a21447ba6853e46de /service/java/com
parent812bc06ef69c687f0a440449273ad78d46da15e0 (diff)
downloadandroid_frameworks_opt_net_wifi-e9b9e8526f976a8942711d546547de6b8c286220.tar.gz
android_frameworks_opt_net_wifi-e9b9e8526f976a8942711d546547de6b8c286220.tar.bz2
android_frameworks_opt_net_wifi-e9b9e8526f976a8942711d546547de6b8c286220.zip
WifiNetworkFactory: Persist user approvals
Persist the list of approved access points for each app. Bug: 122658039 Test: ./frameworks/opt/net/wifi/tests/wifitests/runtests.sh Test: act.py -c wifi_manager.config -tb dut-name -tc WifiNetworkRequestTest Test: act.py -c wifi_manager.config -tb dut-name -tc WifiNetworkRequestTest :test_connect_to_wpa_psk_2g_which_is_already_approved Change-Id: Iec0450ccadf04c3168088b456bb33ed6a786ac8e
Diffstat (limited to 'service/java/com')
-rw-r--r--service/java/com/android/server/wifi/NetworkRequestStoreData.java279
-rw-r--r--service/java/com/android/server/wifi/WifiInjector.java10
-rw-r--r--service/java/com/android/server/wifi/WifiNetworkFactory.java55
3 files changed, 340 insertions, 4 deletions
diff --git a/service/java/com/android/server/wifi/NetworkRequestStoreData.java b/service/java/com/android/server/wifi/NetworkRequestStoreData.java
new file mode 100644
index 000000000..b74e64423
--- /dev/null
+++ b/service/java/com/android/server/wifi/NetworkRequestStoreData.java
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2018 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.net.MacAddress;
+import android.util.Log;
+
+import com.android.server.wifi.WifiNetworkFactory.AccessPoint;
+import com.android.server.wifi.util.XmlUtil;
+import com.android.server.wifi.util.XmlUtil.WifiConfigurationXmlUtil;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * This class performs serialization and parsing of XML data block that contain the list of WiFi
+ * network request approvals.
+ */
+public class NetworkRequestStoreData implements WifiConfigStore.StoreData {
+ private static final String TAG = "NetworkRequestStoreData";
+
+ private static final String XML_TAG_SECTION_HEADER_NETWORK_REQUEST_MAP =
+ "NetworkRequestMap";
+ private static final String XML_TAG_SECTION_HEADER_APPROVED_ACCESS_POINTS_PER_APP =
+ "ApprovedAccessPointsPerApp";
+ private static final String XML_TAG_REQUESTOR_PACKAGE_NAME = "RequestorPackageName";
+ private static final String XML_TAG_SECTION_HEADER_ACCESS_POINT = "AccessPoint";
+ private static final String XML_TAG_ACCESS_POINT_SSID = WifiConfigurationXmlUtil.XML_TAG_SSID;
+ private static final String XML_TAG_ACCESS_POINT_BSSID = WifiConfigurationXmlUtil.XML_TAG_BSSID;
+ private static final String XML_TAG_ACCESS_POINT_NETWORK_TYPE = "NetworkType";
+
+ /**
+ * Interface define the data source for the network requests store data.
+ */
+ public interface DataSource {
+ /**
+ * Retrieve the approved access points from the data source to serialize them to disk.
+ *
+ * @return Map of package name to a set of {@link AccessPoint}
+ */
+ Map<String, Set<AccessPoint>> toSerialize();
+
+ /**
+ * Set the approved access points in the data source after serializing them from disk.
+ *
+ * @param approvedAccessPoints Map of package name to {@link AccessPoint}
+ */
+ void fromDeserialized(Map<String, Set<AccessPoint>> approvedAccessPoints);
+
+ /**
+ * Clear internal data structure in preparation for user switch or initial store read.
+ */
+ void reset();
+
+ /**
+ * Indicates whether there is new data to serialize.
+ */
+ boolean hasNewDataToSerialize();
+ }
+
+ private final DataSource mDataSource;
+
+ public NetworkRequestStoreData(DataSource dataSource) {
+ mDataSource = dataSource;
+ }
+
+ @Override
+ public void serializeData(XmlSerializer out)
+ throws XmlPullParserException, IOException {
+ serializeApprovedAccessPointsMap(out, mDataSource.toSerialize());
+ }
+
+ @Override
+ public void deserializeData(XmlPullParser in, int outerTagDepth)
+ throws XmlPullParserException, IOException {
+ // Ignore empty reads.
+ if (in == null) {
+ return;
+ }
+ mDataSource.fromDeserialized(parseApprovedAccessPointsMap(in, outerTagDepth));
+ }
+
+ @Override
+ public void resetData() {
+ mDataSource.reset();
+ }
+
+ @Override
+ public boolean hasNewDataToSerialize() {
+ return mDataSource.hasNewDataToSerialize();
+ }
+
+ @Override
+ public String getName() {
+ return XML_TAG_SECTION_HEADER_NETWORK_REQUEST_MAP;
+ }
+
+ @Override
+ public @WifiConfigStore.StoreFileId int getStoreFileId() {
+ return WifiConfigStore.STORE_FILE_USER_GENERAL;
+ }
+
+ /**
+ * Serialize the map of package name to approved access points to an output stream in XML
+ * format.
+ *
+ * @throws XmlPullParserException
+ * @throws IOException
+ */
+ private void serializeApprovedAccessPointsMap(
+ XmlSerializer out, final Map<String, Set<AccessPoint>> approvedAccessPointsMap)
+ throws XmlPullParserException, IOException {
+ if (approvedAccessPointsMap == null) {
+ return;
+ }
+ for (Entry<String, Set<AccessPoint>> entry : approvedAccessPointsMap.entrySet()) {
+ String packageName = entry.getKey();
+ XmlUtil.writeNextSectionStart(out,
+ XML_TAG_SECTION_HEADER_APPROVED_ACCESS_POINTS_PER_APP);
+ XmlUtil.writeNextValue(out, XML_TAG_REQUESTOR_PACKAGE_NAME, packageName);
+ serializeApprovedAccessPoints(out, entry.getValue());
+ XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_APPROVED_ACCESS_POINTS_PER_APP);
+ }
+ }
+
+ /**
+ * Serialize the set of approved access points to an output stream in XML format.
+ *
+ * @throws XmlPullParserException
+ * @throws IOException
+ */
+ private void serializeApprovedAccessPoints(
+ XmlSerializer out, final Set<AccessPoint> approvedAccessPoints)
+ throws XmlPullParserException, IOException {
+ for (AccessPoint approvedAccessPoint : approvedAccessPoints) {
+ serializeApprovedAccessPoint(out, approvedAccessPoint);
+ }
+ }
+
+ /**
+ * Serialize a {@link AccessPoint} to an output stream in XML format.
+ *
+ * @throws XmlPullParserException
+ * @throws IOException
+ */
+ private void serializeApprovedAccessPoint(XmlSerializer out,
+ AccessPoint approvedAccessPoint)
+ throws XmlPullParserException, IOException {
+ XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_ACCESS_POINT);
+ XmlUtil.writeNextValue(out, XML_TAG_ACCESS_POINT_SSID, approvedAccessPoint.ssid);
+ XmlUtil.writeNextValue(out, XML_TAG_ACCESS_POINT_BSSID,
+ approvedAccessPoint.bssid.toString());
+ XmlUtil.writeNextValue(out, XML_TAG_ACCESS_POINT_NETWORK_TYPE,
+ approvedAccessPoint.networkType);
+ XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_ACCESS_POINT);
+ }
+
+ /**
+ * Parse a map of package name to approved access point from an input stream in XML format.
+ *
+ * @throws XmlPullParserException
+ * @throws IOException
+ */
+ private Map<String, Set<AccessPoint>> parseApprovedAccessPointsMap(XmlPullParser in,
+ int outerTagDepth)
+ throws XmlPullParserException, IOException {
+ Map<String, Set<AccessPoint>> approvedAccessPointsMap = new HashMap<>();
+ while (XmlUtil.gotoNextSectionWithNameOrEnd(
+ in, XML_TAG_SECTION_HEADER_APPROVED_ACCESS_POINTS_PER_APP, outerTagDepth)) {
+ // Try/catch only runtime exceptions (like illegal args), any XML/IO exceptions are
+ // fatal and should abort the entire loading process.
+ try {
+ String packageName =
+ (String) XmlUtil.readNextValueWithName(in, XML_TAG_REQUESTOR_PACKAGE_NAME);
+ Set<AccessPoint> approvedAccessPoints =
+ parseApprovedAccessPoints(in, outerTagDepth + 1);
+ approvedAccessPointsMap.put(packageName, approvedAccessPoints);
+ } catch (RuntimeException e) {
+ // Failed to parse this network, skip it.
+ Log.e(TAG, "Failed to parse network suggestion. Skipping...", e);
+ }
+ }
+ return approvedAccessPointsMap;
+ }
+
+ /**
+ * Parse a set of approved access points from an input stream in XML format.
+ *
+ * @throws XmlPullParserException
+ * @throws IOException
+ */
+ private Set<AccessPoint> parseApprovedAccessPoints(XmlPullParser in, int outerTagDepth)
+ throws XmlPullParserException, IOException {
+ Set<AccessPoint> approvedAccessPoints = new HashSet<>();
+ while (XmlUtil.gotoNextSectionWithNameOrEnd(
+ in, XML_TAG_SECTION_HEADER_ACCESS_POINT, outerTagDepth)) {
+ // Try/catch only runtime exceptions (like illegal args), any XML/IO exceptions are
+ // fatal and should abort the entire loading process.
+ try {
+ AccessPoint approvedAccessPoint =
+ parseApprovedAccessPoint(in, outerTagDepth + 1);
+ approvedAccessPoints.add(approvedAccessPoint);
+ } catch (RuntimeException e) {
+ // Failed to parse this network, skip it.
+ Log.e(TAG, "Failed to parse network suggestion. Skipping...", e);
+ }
+ }
+ return approvedAccessPoints;
+ }
+
+ /**
+ * Parse a {@link AccessPoint} from an input stream in XML format.
+ *
+ * @throws XmlPullParserException
+ * @throws IOException
+ */
+ private AccessPoint parseApprovedAccessPoint(XmlPullParser in, int outerTagDepth)
+ throws XmlPullParserException, IOException {
+ String ssid = null;
+ MacAddress bssid = null;
+ int networkType = -1;
+
+ // Loop through and parse out all the elements from the stream within this section.
+ while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
+ String[] valueName = new String[1];
+ Object value = XmlUtil.readCurrentValue(in, valueName);
+ if (valueName[0] == null) {
+ throw new XmlPullParserException("Missing value name");
+ }
+ switch (valueName[0]) {
+ case XML_TAG_ACCESS_POINT_SSID:
+ ssid = (String) value;
+ break;
+ case XML_TAG_ACCESS_POINT_BSSID:
+ bssid = MacAddress.fromString((String) value);
+ break;
+ case XML_TAG_ACCESS_POINT_NETWORK_TYPE:
+ networkType = (int) value;
+ break;
+ default:
+ throw new XmlPullParserException(
+ "Unknown value name found: " + valueName[0]);
+ }
+ }
+ if (ssid == null) {
+ throw new XmlPullParserException("XML parsing of ssid failed");
+ }
+ if (bssid == null) {
+ throw new XmlPullParserException("XML parsing of bssid failed");
+ }
+ if (networkType == -1) {
+ throw new XmlPullParserException("XML parsing of network type failed");
+ }
+ return new AccessPoint(ssid, bssid, networkType);
+ }
+}
+
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 2954608ee..92d1fce1d 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -593,7 +593,15 @@ public class WifiInjector {
(ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE),
(AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE),
mClock, this, wifiConnectivityManager, mWifiConfigManager,
- mWifiPermissionsUtil);
+ mWifiConfigStore, mWifiPermissionsUtil);
+ }
+
+ /**
+ * Construct an instance of {@link NetworkRequestStoreData}.
+ */
+ public NetworkRequestStoreData makeNetworkRequestStoreData(
+ NetworkRequestStoreData.DataSource dataSource) {
+ return new NetworkRequestStoreData(dataSource);
}
/**
diff --git a/service/java/com/android/server/wifi/WifiNetworkFactory.java b/service/java/com/android/server/wifi/WifiNetworkFactory.java
index 0552d2c90..ce83a6d5e 100644
--- a/service/java/com/android/server/wifi/WifiNetworkFactory.java
+++ b/service/java/com/android/server/wifi/WifiNetworkFactory.java
@@ -67,7 +67,6 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
-
/**
* Network factory to handle trusted wifi network requests.
*/
@@ -98,6 +97,7 @@ public class WifiNetworkFactory extends NetworkFactory {
private final WifiInjector mWifiInjector;
private final WifiConnectivityManager mWifiConnectivityManager;
private final WifiConfigManager mWifiConfigManager;
+ private final WifiConfigStore mWifiConfigStore;
private final WifiPermissionsUtil mWifiPermissionsUtil;
private final WifiScanner.ScanSettings mScanSettings;
private final NetworkFactoryScanListener mScanListener;
@@ -128,11 +128,16 @@ public class WifiNetworkFactory extends NetworkFactory {
private boolean mConnectionTimeoutSet = false;
private boolean mIsPeriodicScanPaused = false;
private boolean mWifiEnabled = false;
+ /**
+ * Indicates that we have new data to serialize.
+ */
+ private boolean mHasNewDataToSerialize = false;
/**
* Helper class to store an access point that the user previously approved for a specific app.
+ * TODO(b/123014687): Move to a common util class.
*/
- private static class AccessPoint {
+ public static class AccessPoint {
public final String ssid;
public final MacAddress bssid;
public final @NetworkType int networkType;
@@ -310,12 +315,39 @@ public class WifiNetworkFactory extends NetworkFactory {
return true;
};
+ /**
+ * Module to interact with the wifi config store.
+ */
+ private class NetworkRequestDataSource implements NetworkRequestStoreData.DataSource {
+ @Override
+ public Map<String, Set<AccessPoint>> toSerialize() {
+ // Clear the flag after writing to disk.
+ mHasNewDataToSerialize = false;
+ return mUserApprovedAccessPointMap;
+ }
+
+ @Override
+ public void fromDeserialized(Map<String, Set<AccessPoint>> approvedAccessPointMap) {
+ mUserApprovedAccessPointMap.putAll(approvedAccessPointMap);
+ }
+
+ @Override
+ public void reset() {
+ mUserApprovedAccessPointMap.clear();
+ }
+
+ @Override
+ public boolean hasNewDataToSerialize() {
+ return mHasNewDataToSerialize;
+ }
+ }
public WifiNetworkFactory(Looper looper, Context context, NetworkCapabilities nc,
ActivityManager activityManager, AlarmManager alarmManager,
Clock clock, WifiInjector wifiInjector,
WifiConnectivityManager connectivityManager,
WifiConfigManager configManager,
+ WifiConfigStore configStore,
WifiPermissionsUtil wifiPermissionsUtil) {
super(looper, context, TAG, nc);
mContext = context;
@@ -326,6 +358,7 @@ public class WifiNetworkFactory extends NetworkFactory {
mWifiInjector = wifiInjector;
mWifiConnectivityManager = connectivityManager;
mWifiConfigManager = configManager;
+ mWifiConfigStore = configStore;
mWifiPermissionsUtil = wifiPermissionsUtil;
// Create the scan settings.
mScanSettings = new WifiScanner.ScanSettings();
@@ -338,9 +371,21 @@ public class WifiNetworkFactory extends NetworkFactory {
mRegisteredCallbacks = new ExternalCallbackTracker<INetworkRequestMatchCallback>(mHandler);
mSrcMessenger = new Messenger(new Handler(looper, mNetworkConnectionTriggerCallback));
+ // register the data store for serializing/deserializing data.
+ configStore.registerStoreData(
+ wifiInjector.makeNetworkRequestStoreData(new NetworkRequestDataSource()));
+
setScoreFilter(SCORE_FILTER);
}
+ private void saveToStore() {
+ // Set the flag to let WifiConfigStore that we have new data to write.
+ mHasNewDataToSerialize = true;
+ if (!mWifiConfigManager.saveToStore(true)) {
+ Log.w(TAG, "Failed to save to store");
+ }
+ }
+
/**
* Enable verbose logging.
*/
@@ -549,6 +594,7 @@ public class WifiNetworkFactory extends NetworkFactory {
super.dump(fd, pw, args);
pw.println(TAG + ": mGenericConnectionReqCount " + mGenericConnectionReqCount);
pw.println(TAG + ": mActiveSpecificNetworkRequest " + mActiveSpecificNetworkRequest);
+ pw.println(TAG + ": mUserApprovedAccessPointMap " + mUserApprovedAccessPointMap);
}
/**
@@ -1061,6 +1107,8 @@ public class WifiNetworkFactory extends NetworkFactory {
newUserApprovedAccessPoints.add(approvedAccessPoint);
}
}
+ if (newUserApprovedAccessPoints.isEmpty()) return;
+
String requestorPackageName = mContext.getPackageManager().getNameForUid(
mActiveSpecificNetworkRequestSpecifier.requestorUid);
Set<AccessPoint> approvedAccessPoints =
@@ -1069,11 +1117,12 @@ public class WifiNetworkFactory extends NetworkFactory {
approvedAccessPoints = new HashSet<>();
mUserApprovedAccessPointMap.put(requestorPackageName, approvedAccessPoints);
}
- approvedAccessPoints.addAll(newUserApprovedAccessPoints);
if (mVerboseLoggingEnabled) {
Log.v(TAG, "Adding " + newUserApprovedAccessPoints
+ " to user approved access point for " + requestorPackageName);
}
+ approvedAccessPoints.addAll(newUserApprovedAccessPoints);
+ saveToStore();
}
private String getSimplePackageName(@NonNull String origPackageName) {