summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBartosz Fabianowski <bartfab@google.com>2016-02-12 10:30:55 +0100
committerBartosz Fabianowski <bartfab@google.com>2016-02-12 10:30:55 +0100
commit0fb9cf43830d67894b519c9a6271320c4842a5c0 (patch)
tree776bdaf325ad9741093e799ba774a7ea3090f112
parent75ad7fa297007a0cfe1b5a02f45c78441d819d42 (diff)
downloadandroid_frameworks_opt_net_wifi-0fb9cf43830d67894b519c9a6271320c4842a5c0.tar.gz
android_frameworks_opt_net_wifi-0fb9cf43830d67894b519c9a6271320c4842a5c0.tar.bz2
android_frameworks_opt_net_wifi-0fb9cf43830d67894b519c9a6271320c4842a5c0.zip
Allow managed profile to modify networks
If the current foreground user has a managed profile, apps running in that profile should have the same permissions to add/remove/modify networks as apps running as the foreground user itself. This is a re-submit of https://partner-android-review.googlesource.com/#/c/529950/ with updated unit tests that will also work after merging to N/master. BUG=26867426 Change-Id: If97734abad801ae1264919c91c3ef4236469cfde
-rw-r--r--service/java/com/android/server/wifi/ConfigurationMap.java18
-rw-r--r--service/java/com/android/server/wifi/FrameworkFacade.java14
-rw-r--r--service/java/com/android/server/wifi/WifiConfigStore.java22
-rw-r--r--service/java/com/android/server/wifi/WifiConfigurationUtil.java49
-rw-r--r--service/java/com/android/server/wifi/WifiServiceImpl.java5
-rw-r--r--service/java/com/android/server/wifi/WifiStateMachine.java35
-rw-r--r--tests/wifitests/src/com/android/server/wifi/BinderUtil.java32
-rw-r--r--tests/wifitests/src/com/android/server/wifi/BinderUtilTest.java95
-rw-r--r--tests/wifitests/src/com/android/server/wifi/ConfigurationMapTest.java70
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java84
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java (renamed from tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtil.java)27
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java66
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectionTest.java8
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java221
14 files changed, 673 insertions, 73 deletions
diff --git a/service/java/com/android/server/wifi/ConfigurationMap.java b/service/java/com/android/server/wifi/ConfigurationMap.java
index 809952014..376e8e606 100644
--- a/service/java/com/android/server/wifi/ConfigurationMap.java
+++ b/service/java/com/android/server/wifi/ConfigurationMap.java
@@ -1,7 +1,9 @@
package com.android.server.wifi;
+import android.content.pm.UserInfo;
import android.net.wifi.WifiConfiguration;
import android.os.UserHandle;
+import android.os.UserManager;
import java.util.ArrayList;
import java.util.Collection;
@@ -17,13 +19,20 @@ public class ConfigurationMap {
private final Map<Integer, WifiConfiguration> mPerIDForCurrentUser = new HashMap<>();
private final Map<String, WifiConfiguration> mPerFQDNForCurrentUser = new HashMap<>();
+ private final UserManager mUserManager;
+
private int mCurrentUserId = UserHandle.USER_SYSTEM;
+ ConfigurationMap(UserManager userManager) {
+ mUserManager = userManager;
+ }
+
// RW methods:
public WifiConfiguration put(WifiConfiguration config) {
final WifiConfiguration current = mPerID.put(config.networkId, config);
mPerConfigKey.put(config.configKey().hashCode(), config); // This is ridiculous...
- if (config.isVisibleToUser(mCurrentUserId)) {
+ if (WifiConfigurationUtil.isVisibleToAnyProfile(config,
+ mUserManager.getProfiles(mCurrentUserId))) {
mPerIDForCurrentUser.put(config.networkId, config);
if (config.FQDN != null && config.FQDN.length() > 0) {
mPerFQDNForCurrentUser.put(config.FQDN, config);
@@ -70,18 +79,19 @@ public class ConfigurationMap {
mPerIDForCurrentUser.clear();
mPerFQDNForCurrentUser.clear();
- final int previousUserId = mCurrentUserId;
+ final List<UserInfo> previousUserProfiles = mUserManager.getProfiles(mCurrentUserId);
mCurrentUserId = userId;
+ final List<UserInfo> currentUserProfiles = mUserManager.getProfiles(mCurrentUserId);
final List<WifiConfiguration> hiddenConfigurations = new ArrayList<>();
for (Map.Entry<Integer, WifiConfiguration> entry : mPerID.entrySet()) {
final WifiConfiguration config = entry.getValue();
- if (config.isVisibleToUser(mCurrentUserId)) {
+ if (WifiConfigurationUtil.isVisibleToAnyProfile(config, currentUserProfiles)) {
mPerIDForCurrentUser.put(entry.getKey(), config);
if (config.FQDN != null && config.FQDN.length() > 0) {
mPerFQDNForCurrentUser.put(config.FQDN, config);
}
- } else if (config.isVisibleToUser(previousUserId)) {
+ } else if (WifiConfigurationUtil.isVisibleToAnyProfile(config, previousUserProfiles)) {
hiddenConfigurations.add(config);
}
}
diff --git a/service/java/com/android/server/wifi/FrameworkFacade.java b/service/java/com/android/server/wifi/FrameworkFacade.java
index 2ecfe07cc..ef7d91dab 100644
--- a/service/java/com/android/server/wifi/FrameworkFacade.java
+++ b/service/java/com/android/server/wifi/FrameworkFacade.java
@@ -1,6 +1,7 @@
package com.android.server.wifi;
+import android.app.AppGlobals;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
@@ -8,6 +9,7 @@ import android.net.TrafficStats;
import android.net.ip.IpManager;
import android.os.Handler;
import android.os.IBinder;
+import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
@@ -66,5 +68,15 @@ public class FrameworkFacade {
Context context, String iface, IpManager.Callback callback) {
return new IpManager(context, iface, callback);
}
-}
+ /**
+ * Checks whether the given uid has been granted the given permission.
+ * @param permName the permission to check
+ * @param uid The uid to check
+ * @return {@link PackageManager.PERMISSION_GRANTED} if the permission has been granted and
+ * {@link PackageManager.PERMISSION_DENIED} otherwise
+ */
+ public int checkUidPermission(String permName, int uid) throws RemoteException {
+ return AppGlobals.getPackageManager().checkUidPermission(permName, uid);
+ }
+}
diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java
index cc9e5068f..124a6ad38 100644
--- a/service/java/com/android/server/wifi/WifiConfigStore.java
+++ b/service/java/com/android/server/wifi/WifiConfigStore.java
@@ -18,7 +18,6 @@ package com.android.server.wifi;
import static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID;
-import android.app.AppGlobals;
import android.app.admin.DeviceAdminInfo;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.ContentResolver;
@@ -49,6 +48,7 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Settings;
import android.security.Credentials;
import android.security.KeyChain;
@@ -176,7 +176,7 @@ public class WifiConfigStore extends IpConfigStore {
private static final String PPS_FILE = "/data/misc/wifi/PerProviderSubscription.conf";
/* configured networks with network id as the key */
- private final ConfigurationMap mConfiguredNetworks = new ConfigurationMap();
+ private final ConfigurationMap mConfiguredNetworks;
/* A network id is a unique identifier for a network configured in the
* supplicant. Network ids are generated when the supplicant reads
@@ -549,7 +549,8 @@ public class WifiConfigStore extends IpConfigStore {
private WifiStateMachine mWifiStateMachine;
private FrameworkFacade mFacade;
- WifiConfigStore(Context c, WifiStateMachine w, WifiNative wn, FrameworkFacade f) {
+ WifiConfigStore(Context c, WifiStateMachine w, WifiNative wn, FrameworkFacade f,
+ UserManager userManager) {
mContext = c;
mFacade = f;
mWifiNative = wn;
@@ -681,6 +682,7 @@ public class WifiConfigStore extends IpConfigStore {
boolean hs2on = mContext.getResources().getBoolean(R.bool.config_wifi_hotspot2_enabled);
Log.d(Utils.hs2LogTag(getClass()), "Passpoint is " + (hs2on ? "enabled" : "disabled"));
+ mConfiguredNetworks = new ConfigurationMap(userManager);
mMOManager = new PasspointManagementObjectManager(new File(PPS_FILE), hs2on);
mEnableOsuQueries = true;
mAnqpCache = new AnqpCache();
@@ -972,7 +974,8 @@ public class WifiConfigStore extends IpConfigStore {
boolean selectNetwork(WifiConfiguration config, boolean updatePriorities, int uid) {
if (VDBG) localLogNetwork("selectNetwork", config.networkId);
if (config.networkId == INVALID_NETWORK_ID) return false;
- if (!config.isVisibleToUser(mWifiStateMachine.getCurrentUserId())) {
+ if (!WifiConfigurationUtil.isVisibleToAnyProfile(config,
+ mWifiStateMachine.getCurrentUserProfiles())) {
loge("selectNetwork " + Integer.toString(config.networkId) + ": Network config is not "
+ "visible to current user.");
return false;
@@ -1048,7 +1051,8 @@ public class WifiConfigStore extends IpConfigStore {
return new NetworkUpdateResult(INVALID_NETWORK_ID);
}
- if (!config.isVisibleToUser(mWifiStateMachine.getCurrentUserId())) {
+ if (!WifiConfigurationUtil.isVisibleToAnyProfile(config,
+ mWifiStateMachine.getCurrentUserProfiles())) {
return new NetworkUpdateResult(INVALID_NETWORK_ID);
}
@@ -1267,7 +1271,8 @@ public class WifiConfigStore extends IpConfigStore {
* @return network Id
*/
int addOrUpdateNetwork(WifiConfiguration config, int uid) {
- if (config == null || !config.isVisibleToUser(mWifiStateMachine.getCurrentUserId())) {
+ if (config == null || !WifiConfigurationUtil.isVisibleToAnyProfile(config,
+ mWifiStateMachine.getCurrentUserProfiles())) {
return WifiConfiguration.INVALID_NETWORK_ID;
}
@@ -3393,7 +3398,8 @@ public class WifiConfigStore extends IpConfigStore {
* @param config
*/
public void linkConfiguration(WifiConfiguration config) {
- if (!config.isVisibleToUser(mWifiStateMachine.getCurrentUserId())) {
+ if (!WifiConfigurationUtil.isVisibleToAnyProfile(config,
+ mWifiStateMachine.getCurrentUserProfiles())) {
loge("linkConfiguration: Attempting to link config " + config.configKey()
+ " that is not visible to the current user.");
return;
@@ -4611,7 +4617,7 @@ public class WifiConfigStore extends IpConfigStore {
boolean checkConfigOverridePermission(int uid) {
try {
- return (AppGlobals.getPackageManager().checkUidPermission(
+ return (mFacade.checkUidPermission(
android.Manifest.permission.OVERRIDE_WIFI_CONFIG, uid)
== PackageManager.PERMISSION_GRANTED);
} catch (RemoteException e) {
diff --git a/service/java/com/android/server/wifi/WifiConfigurationUtil.java b/service/java/com/android/server/wifi/WifiConfigurationUtil.java
new file mode 100644
index 000000000..7d0fb3cb3
--- /dev/null
+++ b/service/java/com/android/server/wifi/WifiConfigurationUtil.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 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.content.pm.UserInfo;
+import android.net.wifi.WifiConfiguration;
+import android.os.UserHandle;
+
+import java.util.List;
+
+/**
+ * Helper for working with {@link android.net.wifi.WifiConfiguration} objects.
+ */
+public class WifiConfigurationUtil {
+ /**
+ * Check whether a network configuration is visible to a user or any of its managed profiles.
+ * @param config the network configuration whose visibility should be checked
+ * @param profiles the user IDs of the user itself and all its managed profiles (can be obtained
+ * via {@link android.os.UserManager.getProfiles})
+ * @return whether the network configuration is visible to the user or any of its managed
+ * profiles
+ */
+ public static boolean isVisibleToAnyProfile(WifiConfiguration config, List<UserInfo> profiles) {
+ if (config.shared) {
+ return true;
+ }
+ final int creatorUserId = UserHandle.getUserId(config.creatorUid);
+ for (UserInfo profile : profiles) {
+ if (profile.id == creatorUserId) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index d752182c0..0bc8bb38a 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -313,13 +313,14 @@ public class WifiServiceImpl extends IWifiManager.Stub {
mWifiMetrics = new WifiMetrics();
mTrafficPoller = new WifiTrafficPoller(mContext, wifiThread.getLooper(),
WifiNative.getWlanNativeInterface().getInterfaceName());
- mWifiStateMachine = new WifiStateMachine(mContext, mTrafficPoller, facade, mWifiMetrics);
+ mUserManager = UserManager.get(mContext);
+ mWifiStateMachine = new WifiStateMachine(mContext, mTrafficPoller, facade, mWifiMetrics,
+ mUserManager);
mSettingsStore = new WifiSettingsStore(mContext);
mWifiStateMachine.enableRssiPolling(true);
mBatteryStats = BatteryStatsService.getService();
mPowerManager = context.getSystemService(PowerManager.class);
mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
- mUserManager = UserManager.get(mContext);
mNotificationController = new WifiNotificationController(mContext, mWifiStateMachine);
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java
index 959ab19bd..c27ec2742 100644
--- a/service/java/com/android/server/wifi/WifiStateMachine.java
+++ b/service/java/com/android/server/wifi/WifiStateMachine.java
@@ -40,6 +40,7 @@ import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.DhcpResults;
@@ -90,6 +91,7 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.os.UserManager;
import android.os.WorkSource;
import android.provider.Settings;
import android.telephony.TelephonyManager;
@@ -199,6 +201,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
private final AtomicBoolean mP2pConnected = new AtomicBoolean(false);
private boolean mTemporarilyDisconnectWifi = false;
private final String mPrimaryDeviceType;
+ private final UserManager mUserManager;
/* Scan results handling */
private List<ScanDetail> mScanResults = new ArrayList<>();
@@ -1148,11 +1151,13 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
private FrameworkFacade mFacade;
public WifiStateMachine(Context context, WifiTrafficPoller trafficPoller,
- FrameworkFacade facade, WifiMetrics wifiMetrics) {
+ FrameworkFacade facade, WifiMetrics wifiMetrics,
+ UserManager userManager) {
super("WifiStateMachine");
mWifiMetrics = wifiMetrics;
mContext = context;
mFacade = facade;
+ mUserManager = userManager;
mWifiNative = WifiNative.getWlanNativeInterface();
// TODO refactor WifiNative use of context out into it's own class
@@ -1168,7 +1173,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
mP2pSupported = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_WIFI_DIRECT);
- mWifiConfigStore = new WifiConfigStore(context, this, mWifiNative, facade);
+ mWifiConfigStore = new WifiConfigStore(context, this, mWifiNative, facade, userManager);
mWifiMonitor = WifiMonitor.getInstance();
@@ -7039,7 +7044,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
break;
case CMD_ADD_OR_UPDATE_NETWORK:
// Only the current foreground user can modify networks.
- if (UserHandle.getUserId(message.sendingUid) != mCurrentUserId) {
+ if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) {
loge("Only the current foreground user can modify networks "
+ " currentUserId=" + mCurrentUserId
+ " sendingUserId=" + UserHandle.getUserId(message.sendingUid));
@@ -7090,7 +7095,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
break;
case CMD_REMOVE_NETWORK:
// Only the current foreground user can modify networks.
- if (UserHandle.getUserId(message.sendingUid) != mCurrentUserId) {
+ if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) {
loge("Only the current foreground user can modify networks "
+ " currentUserId=" + mCurrentUserId
+ " sendingUserId=" + UserHandle.getUserId(message.sendingUid));
@@ -7116,7 +7121,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
break;
case CMD_ENABLE_NETWORK:
// Only the current foreground user can modify networks.
- if (UserHandle.getUserId(message.sendingUid) != mCurrentUserId) {
+ if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) {
loge("Only the current foreground user can modify networks "
+ " currentUserId=" + mCurrentUserId
+ " sendingUserId=" + UserHandle.getUserId(message.sendingUid));
@@ -7385,7 +7390,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
// lastConnectUid on a per-user basis.
int lastConnectUid = WifiConfiguration.UNKNOWN_UID;
if (mWifiConfigStore.isLastSelectedConfiguration(config)
- && UserHandle.getUserId(config.lastConnectUid) == mCurrentUserId) {
+ && isCurrentUserProfile(UserHandle.getUserId(config.lastConnectUid))) {
lastConnectUid = config.lastConnectUid;
}
mWifiMetrics.startConnectionEvent(mWifiInfo, config,
@@ -7451,7 +7456,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
break;
case WifiManager.CONNECT_NETWORK:
// Only the current foreground user can modify networks.
- if (UserHandle.getUserId(message.sendingUid) != mCurrentUserId) {
+ if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) {
loge("Only the current foreground user can modify networks "
+ " currentUserId=" + mCurrentUserId
+ " sendingUserId=" + UserHandle.getUserId(message.sendingUid));
@@ -7599,7 +7604,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
// Fall thru
case WifiStateMachine.CMD_AUTO_SAVE_NETWORK:
// Only the current foreground user can modify networks.
- if (UserHandle.getUserId(message.sendingUid) != mCurrentUserId) {
+ if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) {
loge("Only the current foreground user can modify networks "
+ " currentUserId=" + mCurrentUserId
+ " sendingUserId=" + UserHandle.getUserId(message.sendingUid));
@@ -7698,7 +7703,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
break;
case WifiManager.FORGET_NETWORK:
// Only the current foreground user can modify networks.
- if (UserHandle.getUserId(message.sendingUid) != mCurrentUserId) {
+ if (!isCurrentUserProfile(UserHandle.getUserId(message.sendingUid))) {
loge("Only the current foreground user can modify networks "
+ " currentUserId=" + mCurrentUserId
+ " sendingUserId=" + UserHandle.getUserId(message.sendingUid));
@@ -10051,6 +10056,18 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
return mCurrentUserId;
}
+ private boolean isCurrentUserProfile(int userId) {
+ if (userId == mCurrentUserId) {
+ return true;
+ }
+ final UserInfo parent = mUserManager.getProfileParent(userId);
+ return parent != null && parent.id == mCurrentUserId;
+ }
+
+ public List<UserInfo> getCurrentUserProfiles() {
+ return mUserManager.getProfiles(mCurrentUserId);
+ }
+
/**
* @param reason reason code from supplicant on network disconnected event
* @return true if this is a suspicious disconnect
diff --git a/tests/wifitests/src/com/android/server/wifi/BinderUtil.java b/tests/wifitests/src/com/android/server/wifi/BinderUtil.java
new file mode 100644
index 000000000..107de7c8d
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/BinderUtil.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2016 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.os.Binder;
+
+/**
+ * Utilities for faking the calling uid in Binder.
+ */
+public class BinderUtil {
+ /**
+ * Fake the calling uid in Binder.
+ * @param uid the calling uid that Binder should return from now on
+ */
+ public static void setUid(int uid) {
+ Binder.restoreCallingIdentity((((long) uid) << 32) | Binder.getCallingPid());
+ }
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/BinderUtilTest.java b/tests/wifitests/src/com/android/server/wifi/BinderUtilTest.java
new file mode 100644
index 000000000..925bdc0c2
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/BinderUtilTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2016 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import android.os.Binder;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link com.android.server.wifi.BinderUtil}.
+ */
+@SmallTest
+public class BinderUtilTest {
+ static final int FAKE_UID = 30000000;
+
+ private long mToken;
+
+ /**
+ * Sets up the test harness before running a test.
+ */
+ @Before
+ public void setUp() {
+ mToken = Binder.clearCallingIdentity();
+ }
+
+ /**
+ * Cleans up the test harness after running a test.
+ */
+ @After
+ public void cleanUp() {
+ Binder.restoreCallingIdentity(mToken);
+ }
+
+ /**
+ * Test using {@link BinderUtil.setUid} to set and restore the Binder uid.
+ */
+ @Test
+ public void setUid() {
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ assertFalse(uid == FAKE_UID);
+
+ // Verify that setUid() can be used to fake the Binder uid without affecting the pid.
+ BinderUtil.setUid(FAKE_UID);
+ assertEquals(pid, Binder.getCallingPid());
+ assertEquals(FAKE_UID, Binder.getCallingUid());
+
+ // Verify that setUid() can be used to restore the original Binder uid without affecting the
+ // pid.
+ BinderUtil.setUid(uid);
+ assertEquals(pid, Binder.getCallingPid());
+ assertEquals(uid, Binder.getCallingUid());
+ }
+
+ /**
+ * Test using {@link BinderUtil.setUid} to set the Binder uid and
+ * {@link Binder.restoreCallingIdentity} to restore it.
+ */
+ @Test
+ public void setUidAndRestoreCallingIdentity() {
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ assertFalse(uid == FAKE_UID);
+
+ // Verify that setUid() can be used to fake the Binder uid without affecting the pid.
+ BinderUtil.setUid(FAKE_UID);
+ assertEquals(pid, Binder.getCallingPid());
+ assertEquals(FAKE_UID, Binder.getCallingUid());
+
+ // Verify that the setUid() calls above did not break Binder.restoreCallingIdentity().
+ Binder.restoreCallingIdentity(mToken);
+ assertEquals(pid, Binder.getCallingPid());
+ assertEquals(uid, Binder.getCallingUid());
+ }
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/ConfigurationMapTest.java b/tests/wifitests/src/com/android/server/wifi/ConfigurationMapTest.java
index 917fd77a7..328feaf75 100644
--- a/tests/wifitests/src/com/android/server/wifi/ConfigurationMapTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/ConfigurationMapTest.java
@@ -18,12 +18,22 @@ package com.android.server.wifi;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.when;
+import android.content.pm.UserInfo;
import android.net.wifi.WifiConfiguration;
import android.os.UserHandle;
+import android.os.UserManager;
import android.test.suitebuilder.annotation.SmallTest;
+import android.util.SparseArray;
+import com.android.server.wifi.MockAnswerUtil.AnswerWithArguments;
+
+import org.junit.Before;
import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.Arrays;
@@ -37,25 +47,56 @@ import java.util.Set;
@SmallTest
public class ConfigurationMapTest {
private static final List<WifiConfiguration> CONFIGS = Arrays.asList(
- WifiConfigurationUtil.generateWifiConfig(0, 1000000, "\"red\"", true, true, null, null),
- WifiConfigurationUtil.generateWifiConfig(
- 1, 1000001, "\"green\"", false, true, null, null),
- WifiConfigurationUtil.generateWifiConfig(
- 2, 1000002, "\"blue\"", true, false, "example.com", "Blue"),
- WifiConfigurationUtil.generateWifiConfig(
+ WifiConfigurationTestUtil.generateWifiConfig(
+ 0, 1000000, "\"red\"", true, true, null, null),
+ WifiConfigurationTestUtil.generateWifiConfig(
+ 1, 1000001, "\"green\"", true, false, "example.com", "Green"),
+ WifiConfigurationTestUtil.generateWifiConfig(
+ 2, 1200000, "\"blue\"", false, true, null, null),
+ WifiConfigurationTestUtil.generateWifiConfig(
3, 1100000, "\"cyan\"", true, true, null, null),
- WifiConfigurationUtil.generateWifiConfig(
- 4, 1100001, "\"yellow\"", false, false, null, null),
- WifiConfigurationUtil.generateWifiConfig(
- 5, 1100002, "\"magenta\"", true, true, "example.org", "Magenta"));
+ WifiConfigurationTestUtil.generateWifiConfig(
+ 4, 1100001, "\"yellow\"", true, true, "example.org", "Yellow"),
+ WifiConfigurationTestUtil.generateWifiConfig(
+ 5, 1100002, "\"magenta\"", false, false, null, null));
+
+ private static final SparseArray<List<UserInfo>> USER_PROFILES = new SparseArray<>();
+ static {
+ USER_PROFILES.put(UserHandle.USER_SYSTEM, Arrays.asList(
+ new UserInfo(UserHandle.USER_SYSTEM, "Owner", 0),
+ new UserInfo(12, "Managed Profile", 0)));
+ USER_PROFILES.put(10, Arrays.asList(new UserInfo(10, "Alice", 0)));
+ USER_PROFILES.put(11, Arrays.asList(new UserInfo(11, "Bob", 0)));
+ }
+
+ @Mock UserManager mUserManager;
private int mCurrentUserId = UserHandle.USER_SYSTEM;
- private final ConfigurationMap mConfigs = new ConfigurationMap();
+ private ConfigurationMap mConfigs;
+
+ /**
+ * Sets up the test harness before running a test.
+ */
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ when(mUserManager.getProfiles(anyInt()))
+ .then(new AnswerWithArguments() {
+ public List<UserInfo> answer(int userId) {
+ return USER_PROFILES.get(userId);
+ }
+ });
+ mConfigs = new ConfigurationMap(mUserManager);
+ }
public void switchUser(int newUserId) {
Set<WifiConfiguration> hiddenConfigurations = new HashSet<>();
for (WifiConfiguration config : mConfigs.valuesForAllUsers()) {
- if (config.isVisibleToUser(mCurrentUserId) && !config.isVisibleToUser(newUserId)) {
+ if (WifiConfigurationUtil.isVisibleToAnyProfile(config,
+ USER_PROFILES.get(mCurrentUserId))
+ && !WifiConfigurationUtil.isVisibleToAnyProfile(config,
+ USER_PROFILES.get(newUserId))) {
hiddenConfigurations.add(config);
}
}
@@ -73,7 +114,8 @@ public class ConfigurationMapTest {
// user. Also, check that *ForAllUsers() methods can be used to access all network
// configurations, irrespective of their visibility to the current user.
for (WifiConfiguration config : configs) {
- if (config.isVisibleToUser(mCurrentUserId)) {
+ if (WifiConfigurationUtil.isVisibleToAnyProfile(config,
+ USER_PROFILES.get(mCurrentUserId))) {
configsForCurrentUser.add(config);
if (config.status != WifiConfiguration.Status.DISABLED) {
enabledConfigsForCurrentUser.add(config);
@@ -176,7 +218,7 @@ public class ConfigurationMapTest {
configs.add(config2);
verifyGetters(configs);
- // Add |config3|.
+ // Add |config3|, which belongs to a managed profile of the current user.
final WifiConfiguration config3 = CONFIGS.get(2);
assertNull(mConfigs.put(config3));
// Verify that the getters return |config2| and |config3|.
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java
index 98cd4e09f..5e24aa0d7 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java
@@ -37,6 +37,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.content.pm.UserInfo;
import android.net.wifi.FakeKeys;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
@@ -45,11 +46,13 @@ import android.net.wifi.WifiEnterpriseConfig.Eap;
import android.net.wifi.WifiEnterpriseConfig.Phase2;
import android.os.Process;
import android.os.UserHandle;
+import android.os.UserManager;
import android.security.Credentials;
import android.support.test.InstrumentationRegistry;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.TextUtils;
import android.util.Log;
+import android.util.SparseArray;
import com.android.server.net.DelayedDiskWrite;
import com.android.server.wifi.MockAnswerUtil.AnswerWithArguments;
@@ -94,20 +97,33 @@ import java.util.TreeMap;
@SmallTest
public class WifiConfigStoreTest {
private static final List<WifiConfiguration> CONFIGS = Arrays.asList(
- WifiConfigurationUtil.generateWifiConfig(
+ WifiConfigurationTestUtil.generateWifiConfig(
0, 1000000, "\"red\"", true, true, null, null),
- WifiConfigurationUtil.generateWifiConfig(
+ WifiConfigurationTestUtil.generateWifiConfig(
1, 1000001, "\"green\"", true, true, "example.com", "Green"),
- WifiConfigurationUtil.generateWifiConfig(
- 2, 1100000, "\"blue\"", false, true, "example.org", "Blue"));
+ WifiConfigurationTestUtil.generateWifiConfig(
+ 2, 1100000, "\"blue\"", false, true, "example.org", "Blue"),
+ WifiConfigurationTestUtil.generateWifiConfig(
+ 3, 1200000, "\"cyan\"", false, true, null, null));
private static final int[] USER_IDS = {0, 10, 11};
+ private static final int MANAGED_PROFILE_USER_ID = 12;
+ private static final int MANAGED_PROFILE_PARENT_USER_ID = 0;
+ private static final SparseArray<List<UserInfo>> USER_PROFILES = new SparseArray<>();
+ static {
+ USER_PROFILES.put(0, Arrays.asList(new UserInfo(0, "Owner", 0),
+ new UserInfo(12, "Managed Profile", 0)));
+ USER_PROFILES.put(10, Arrays.asList(new UserInfo(10, "Alice", 0)));
+ USER_PROFILES.put(11, Arrays.asList(new UserInfo(11, "Bob", 0)));
+ }
+
private static final Map<Integer, List<WifiConfiguration>> VISIBLE_CONFIGS = new HashMap<>();
static {
for (int userId : USER_IDS) {
List<WifiConfiguration> configs = new ArrayList<>();
for (int i = 0; i < CONFIGS.size(); ++i) {
- if (CONFIGS.get(i).isVisibleToUser(userId)) {
+ if (WifiConfigurationUtil.isVisibleToAnyProfile(CONFIGS.get(i),
+ USER_PROFILES.get(userId))) {
configs.add(CONFIGS.get(i));
}
}
@@ -120,6 +136,7 @@ public class WifiConfigStoreTest {
@Mock private WifiStateMachine mWifiStateMachine;
@Mock private WifiNative mWifiNative;
@Mock private FrameworkFacade mFrameworkFacade;
+ @Mock private UserManager mUserManager;
@Mock private DelayedDiskWrite mWriter;
@Mock private PasspointManagementObjectManager mMOManager;
private WifiConfigStore mConfigStore;
@@ -140,9 +157,15 @@ public class WifiConfigStoreTest {
when(mContext.getPackageManager()).thenReturn(realContext.getPackageManager());
when(mWifiStateMachine.getCurrentUserId()).thenReturn(UserHandle.USER_SYSTEM);
+ when(mWifiStateMachine.getCurrentUserProfiles())
+ .thenReturn(USER_PROFILES.get(UserHandle.USER_SYSTEM));
+
+ for (int userId : USER_IDS) {
+ when(mUserManager.getProfiles(userId)).thenReturn(USER_PROFILES.get(userId));
+ }
mConfigStore = new WifiConfigStore(mContext, mWifiStateMachine, mWifiNative,
- mFrameworkFacade);
+ mFrameworkFacade, mUserManager);
final Field configuredNetworksField =
WifiConfigStore.class.getDeclaredField("mConfiguredNetworks");
@@ -175,11 +198,18 @@ public class WifiConfigStoreTest {
private void switchUser(int newUserId) {
when(mWifiStateMachine.getCurrentUserId()).thenReturn(newUserId);
+ when(mWifiStateMachine.getCurrentUserProfiles())
+ .thenReturn(USER_PROFILES.get(newUserId));
mConfigStore.handleUserSwitch();
}
- private void switchUserToCreatorOf(WifiConfiguration config) {
- switchUser(UserHandle.getUserId(config.creatorUid));
+ private void switchUserToCreatorOrParentOf(WifiConfiguration config) {
+ final int creatorUserId = UserHandle.getUserId(config.creatorUid);
+ if (creatorUserId == MANAGED_PROFILE_USER_ID) {
+ switchUser(MANAGED_PROFILE_PARENT_USER_ID);
+ } else {
+ switchUser(creatorUserId);
+ }
}
private void addNetworks() throws Exception {
@@ -190,7 +220,7 @@ public class WifiConfigStoreTest {
.thenReturn(true);
for (int i = 0; i < CONFIGS.size(); ++i) {
assertEquals(i, CONFIGS.get(i).networkId);
- switchUserToCreatorOf(CONFIGS.get(i));
+ switchUserToCreatorOrParentOf(CONFIGS.get(i));
final WifiConfiguration config = new WifiConfiguration(CONFIGS.get(i));
config.networkId = -1;
when(mWifiNative.addNetwork()).thenReturn(i);
@@ -293,7 +323,8 @@ public class WifiConfigStoreTest {
for (WifiConfiguration expectedConfig: CONFIGS) {
final WifiConfiguration actualConfig =
mConfigStore.getWifiConfiguration(expectedConfig.networkId);
- if (expectedConfig.isVisibleToUser(userId)) {
+ if (WifiConfigurationUtil.isVisibleToAnyProfile(expectedConfig,
+ USER_PROFILES.get(userId))) {
verifyNetworkConfig(expectedConfig, actualConfig);
} else {
assertNull(actualConfig);
@@ -314,7 +345,8 @@ public class WifiConfigStoreTest {
for (WifiConfiguration expectedConfig: CONFIGS) {
final WifiConfiguration actualConfig =
mConfigStore.getWifiConfiguration(expectedConfig.configKey());
- if (expectedConfig.isVisibleToUser(userId)) {
+ if (WifiConfigurationUtil.isVisibleToAnyProfile(expectedConfig,
+ USER_PROFILES.get(userId))) {
verifyNetworkConfig(expectedConfig, actualConfig);
} else {
assertNull(actualConfig);
@@ -347,7 +379,8 @@ public class WifiConfigStoreTest {
mConfigStore.enableAllNetworks();
for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) {
- assertEquals(config.isVisibleToUser(userId),
+ assertEquals(WifiConfigurationUtil.isVisibleToAnyProfile(config,
+ USER_PROFILES.get(userId)),
config.getNetworkSelectionStatus().isNetworkEnabled());
}
}
@@ -374,7 +407,8 @@ public class WifiConfigStoreTest {
final WifiNative wifiNative = createNewWifiNativeMock();
final boolean success =
mConfigStore.selectNetwork(config, false, config.creatorUid);
- if (!config.isVisibleToUser(userId)) {
+ if (!WifiConfigurationUtil.isVisibleToAnyProfile(config,
+ USER_PROFILES.get(userId))) {
// If the network configuration is not visible to the current user, verify that
// nothing changed.
assertFalse(success);
@@ -395,7 +429,8 @@ public class WifiConfigStoreTest {
verify(wifiNative, never()).enableNetwork(intThat(not(config.networkId)),
anyBoolean());
for (WifiConfiguration config2 : mConfiguredNetworks.valuesForAllUsers()) {
- if (config2.isVisibleToUser(userId)
+ if (WifiConfigurationUtil.isVisibleToAnyProfile(config2,
+ USER_PROFILES.get(userId))
&& config2.networkId != config.networkId) {
assertEquals(WifiConfiguration.Status.DISABLED, config2.status);
} else {
@@ -416,7 +451,7 @@ public class WifiConfigStoreTest {
*/
private void verifySaveNetwork(int network) throws Exception {
// Switch to the correct user.
- switchUserToCreatorOf(CONFIGS.get(network));
+ switchUserToCreatorOrParentOf(CONFIGS.get(network));
// Set up wpa_supplicant.
when(mWifiNative.addNetwork()).thenReturn(0);
@@ -543,14 +578,21 @@ public class WifiConfigStoreTest {
.thenReturn(null);
when(mWifiNative.getNetworkVariable(1, WifiConfigStore.ID_STRING_VAR_NAME))
.thenReturn('"' + CONFIGS.get(1).FQDN + '"');
- // Up-to-date configuration: Metadata in "id_str".
- final Map<String, String> metadata = new HashMap<String, String>();
+ // Up-to-date Hotspot 2.0 network configuration: Metadata in "id_str".
+ Map<String, String> metadata = new HashMap<String, String>();
metadata.put(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY, CONFIGS.get(2).configKey());
metadata.put(WifiConfigStore.ID_STRING_KEY_CREATOR_UID,
Integer.toString(CONFIGS.get(2).creatorUid));
metadata.put(WifiConfigStore.ID_STRING_KEY_FQDN, CONFIGS.get(2).FQDN);
when(mWifiNative.getNetworkExtra(2, WifiConfigStore.ID_STRING_VAR_NAME))
.thenReturn(metadata);
+ // Up-to-date regular network configuration: Metadata in "id_str".
+ metadata = new HashMap<String, String>();
+ metadata.put(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY, CONFIGS.get(3).configKey());
+ metadata.put(WifiConfigStore.ID_STRING_KEY_CREATOR_UID,
+ Integer.toString(CONFIGS.get(3).creatorUid));
+ when(mWifiNative.getNetworkExtra(3, WifiConfigStore.ID_STRING_VAR_NAME))
+ .thenReturn(metadata);
// Set up networkHistory.txt file.
final File file = File.createTempFile("networkHistory.txt", null);
@@ -647,9 +689,10 @@ public class WifiConfigStoreTest {
final Collection<WifiConfiguration> oldConfigs = mConfiguredNetworks.valuesForAllUsers();
int expectedNumberOfConfigs = oldConfigs.size();
for (WifiConfiguration config : oldConfigs) {
- if (config.isVisibleToUser(oldUserId)) {
+ if (WifiConfigurationUtil.isVisibleToAnyProfile(config, USER_PROFILES.get(oldUserId))) {
config.status = WifiConfiguration.Status.ENABLED;
- if (config.isVisibleToUser(newUserId)) {
+ if (WifiConfigurationUtil.isVisibleToAnyProfile(config,
+ USER_PROFILES.get(newUserId))) {
if (makeOneConfigEphemeral && removedEphemeralConfig == null) {
config.ephemeral = true;
lastSelectedConfigurationField.set(mConfigStore, config.configKey());
@@ -660,7 +703,8 @@ public class WifiConfigStoreTest {
}
} else {
config.status = WifiConfiguration.Status.DISABLED;
- if (config.isVisibleToUser(newUserId)) {
+ if (WifiConfigurationUtil.isVisibleToAnyProfile(config,
+ USER_PROFILES.get(newUserId))) {
newUserOnlyConfigs.add(config);
} else {
neitherUserConfigs.add(config);
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtil.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java
index 1368fc1c2..7117c2a61 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtil.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
package com.android.server.wifi;
@@ -22,7 +22,7 @@ import android.net.wifi.WifiEnterpriseConfig;
/**
* Helper for creating and populating WifiConfigurations in unit tests.
*/
-public class WifiConfigurationUtil {
+public class WifiConfigurationTestUtil {
/**
* These values are used to describe AP's security setting. One AP can support multiple of them,
* only if there is no conflict.
@@ -32,6 +32,17 @@ public class WifiConfigurationUtil {
public static final int SECURITY_PSK = 1 << 1;
public static final int SECURITY_EAP = 1 << 2;
+ /**
+ * Construct a {@link android.net.wifi.WifiConfiguration}.
+ * @param networkId the configuration's networkId
+ * @param uid the configuration's creator uid
+ * @param ssid the configuration's ssid
+ * @param shared whether the configuration is shared with other users on the device
+ * @param enabled whether the configuration is enabled
+ * @param fqdn the configuration's FQDN (Hotspot 2.0 only)
+ * @param providerFriendlyName the configuration's provider's friendly name (Hotspot 2.0 only)
+ * @return the constructed {@link android.net.wifi.WifiConfiguration}
+ */
public static WifiConfiguration generateWifiConfig(int networkId, int uid, String ssid,
boolean shared, boolean enabled, String fqdn, String providerFriendlyName) {
final WifiConfiguration config = new WifiConfiguration();
@@ -49,6 +60,18 @@ public class WifiConfigurationUtil {
return config;
}
+ /**
+ * Construct a {@link android.net.wifi.WifiConfiguration}.
+ * @param networkId the configuration's networkId
+ * @param uid the configuration's creator uid
+ * @param ssid the configuration's ssid
+ * @param shared whether the configuration is shared with other users on the device
+ * @param enabled whether the configuration is enabled
+ * @param fqdn the configuration's FQDN (Hotspot 2.0 only)
+ * @param providerFriendlyName the configuration's provider's friendly name (Hotspot 2.0 only)
+ * @param security the configuration's security type
+ * @return the constructed {@link android.net.wifi.WifiConfiguration}
+ */
public static WifiConfiguration generateWifiConfig(int networkId, int uid, String ssid,
boolean shared, boolean enabled, String fqdn, String providerFriendlyName,
int security) {
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java
new file mode 100644
index 000000000..c5b50300e
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 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 static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.content.pm.UserInfo;
+import android.net.wifi.WifiConfiguration;
+import android.os.UserHandle;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Unit tests for {@link com.android.server.wifi.WifiConfigurationUtil}.
+ */
+@SmallTest
+public class WifiConfigurationUtilTest {
+ static final int CURRENT_USER_ID = 0;
+ static final int CURRENT_USER_MANAGED_PROFILE_USER_ID = 10;
+ static final int OTHER_USER_ID = 11;
+ static final List<UserInfo> PROFILES = Arrays.asList(
+ new UserInfo(CURRENT_USER_ID, "owner", 0),
+ new UserInfo(CURRENT_USER_MANAGED_PROFILE_USER_ID, "managed profile", 0));
+
+ /**
+ * Test for {@link WifiConfigurationUtil.isVisibleToAnyProfile}.
+ */
+ @Test
+ public void isVisibleToAnyProfile() {
+ // Shared network configuration created by another user.
+ final WifiConfiguration configuration = new WifiConfiguration();
+ configuration.creatorUid = UserHandle.getUid(OTHER_USER_ID, 0);
+ assertTrue(WifiConfigurationUtil.isVisibleToAnyProfile(configuration, PROFILES));
+
+ // Private network configuration created by another user.
+ configuration.shared = false;
+ assertFalse(WifiConfigurationUtil.isVisibleToAnyProfile(configuration, PROFILES));
+
+ // Private network configuration created by the current user.
+ configuration.creatorUid = UserHandle.getUid(CURRENT_USER_ID, 0);
+ assertTrue(WifiConfigurationUtil.isVisibleToAnyProfile(configuration, PROFILES));
+
+ // Private network configuration created by the current user's managed profile.
+ configuration.creatorUid = UserHandle.getUid(CURRENT_USER_MANAGED_PROFILE_USER_ID, 0);
+ assertTrue(WifiConfigurationUtil.isVisibleToAnyProfile(configuration, PROFILES));
+ }
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectionTest.java b/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectionTest.java
index 0d35f5fcb..f6967aa74 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectionTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectionTest.java
@@ -16,10 +16,10 @@
package com.android.server.wifi;
-import static com.android.server.wifi.WifiConfigurationUtil.SECURITY_EAP;
-import static com.android.server.wifi.WifiConfigurationUtil.SECURITY_NONE;
-import static com.android.server.wifi.WifiConfigurationUtil.SECURITY_PSK;
-import static com.android.server.wifi.WifiConfigurationUtil.generateWifiConfig;
+import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_EAP;
+import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_NONE;
+import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_PSK;
+import static com.android.server.wifi.WifiConfigurationTestUtil.generateWifiConfig;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.anyInt;
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
index 200dc9348..183b15618 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
@@ -17,13 +17,16 @@
package com.android.server.wifi;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyObject;
import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;
@@ -31,6 +34,7 @@ import static org.mockito.Mockito.withSettings;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.DhcpResults;
@@ -43,6 +47,7 @@ import android.net.wifi.WifiManager;
import android.net.wifi.WifiSsid;
import android.net.wifi.p2p.IWifiP2pManager;
import android.os.BatteryStats;
+import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -54,6 +59,7 @@ import android.os.Message;
import android.os.Messenger;
import android.os.PowerManager;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Settings;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
@@ -81,6 +87,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -92,6 +99,11 @@ import java.util.Map;
public class WifiStateMachineTest {
public static final String TAG = "WifiStateMachineTest";
+ private static final int MANAGED_PROFILE_UID = 1100000;
+ private static final int OTHER_USER_UID = 1200000;
+
+ private long mBinderToken;
+
private static <T> T mockWithInterfaces(Class<T> class1, Class<?>... interfaces) {
return mock(class1, withSettings().extraInterfaces(interfaces));
}
@@ -135,7 +147,7 @@ public class WifiStateMachineTest {
}
}
- private FrameworkFacade getFrameworkFacade() throws InterruptedException {
+ private FrameworkFacade getFrameworkFacade() throws Exception {
FrameworkFacade facade = mock(FrameworkFacade.class);
when(facade.makeBaseLogger()).thenReturn(mock(BaseWifiLogger.class));
@@ -178,6 +190,9 @@ public class WifiStateMachineTest {
}
});
+ when(facade.checkUidPermission(eq(android.Manifest.permission.OVERRIDE_WIFI_CONFIG),
+ anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
+
return facade;
}
@@ -300,6 +315,7 @@ public class WifiStateMachineTest {
@Mock WifiNative mWifiNative;
@Mock SupplicantStateTracker mSupplicantStateTracker;
@Mock WifiMetrics mWifiMetrics;
+ @Mock UserManager mUserManager;
public WifiStateMachineTest() throws Exception {
}
@@ -337,7 +353,13 @@ public class WifiStateMachineTest {
any(Context.class), any(WifiStateMachine.class), any(WifiConfigStore.class),
any(Handler.class))).thenReturn(mSupplicantStateTracker);
- mWsm = new WifiStateMachine(context, null, factory, mWifiMetrics);
+ when(mUserManager.getProfileParent(11))
+ .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "owner", 0));
+ when(mUserManager.getProfiles(UserHandle.USER_SYSTEM)).thenReturn(Arrays.asList(
+ new UserInfo(UserHandle.USER_SYSTEM, "owner", 0),
+ new UserInfo(11, "managed profile", 0)));
+
+ mWsm = new WifiStateMachine(context, null, factory, mWifiMetrics, mUserManager);
mWsmThread = getWsmHandlerThread(mWsm);
final Object sync = new Object();
@@ -372,10 +394,13 @@ public class WifiStateMachineTest {
}
/* Now channel is supposed to be connected */
+
+ mBinderToken = Binder.clearCallingIdentity();
}
@After
public void cleanUp() throws Exception {
+ Binder.restoreCallingIdentity(mBinderToken);
if (mSyncThread != null) stopLooper(mSyncThread.getLooper());
if (mWsmThread != null) stopLooper(mWsmThread.getLooper());
@@ -447,8 +472,7 @@ public class WifiStateMachineTest {
assertEquals("InitialState", getCurrentState().getName());
}
- @Test
- public void addNetwork() throws Exception {
+ private void addNetworkAndVerifySuccess() throws Exception {
loadComponents();
@@ -516,10 +540,189 @@ public class WifiStateMachineTest {
assertTrue(config2.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE));
}
+ private void addNetworkAndVerifyFailure() throws Exception {
+ loadComponents();
+
+ final WifiConfiguration config = new WifiConfiguration();
+ config.SSID = sSSID;
+ config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+
+ mWsm.syncAddOrUpdateNetwork(mWsmAsyncChannel, config);
+ wait(200);
+
+ verify(mWifiNative, never()).addNetwork();
+ verify(mWifiNative, never()).setNetworkVariable(anyInt(), anyString(), anyString());
+
+ assertTrue(mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).isEmpty());
+ }
+
+ /**
+ * Verifies that the current foreground user is allowed to add a network.
+ */
+ @Test
+ public void addNetworkAsCurrentUser() throws Exception {
+ addNetworkAndVerifySuccess();
+ }
+
+ /**
+ * Verifies that a managed profile of the current foreground user is allowed to add a network.
+ */
+ @Test
+ public void addNetworkAsCurrentUsersManagedProfile() throws Exception {
+ BinderUtil.setUid(MANAGED_PROFILE_UID);
+ addNetworkAndVerifySuccess();
+ }
+
+ /**
+ * Verifies that a background user is not allowed to add a network.
+ */
+ @Test
+ public void addNetworkAsOtherUser() throws Exception {
+ BinderUtil.setUid(OTHER_USER_UID);
+ addNetworkAndVerifyFailure();
+ }
+
+ private void removeNetworkAndVerifySuccess() throws Exception {
+ when(mWifiNative.removeNetwork(0)).thenReturn(true);
+ assertTrue(mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0));
+ wait(200);
+ assertTrue(mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).isEmpty());
+ }
+
+ private void removeNetworkAndVerifyFailure() throws Exception {
+ assertFalse(mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0));
+ wait(200);
+ assertEquals(1, mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).size());
+ verify(mWifiNative, never()).removeNetwork(anyInt());
+ }
+
+ /**
+ * Verifies that the current foreground user is allowed to remove a network.
+ */
+ @Test
+ public void removeNetworkAsCurrentUser() throws Exception {
+ addNetworkAndVerifySuccess();
+ removeNetworkAndVerifySuccess();
+ }
+
+ /**
+ * Verifies that a managed profile of the current foreground user is allowed to remove a
+ * network.
+ */
+ @Test
+ public void removeNetworkAsCurrentUsersManagedProfile() throws Exception {
+ addNetworkAndVerifySuccess();
+ BinderUtil.setUid(MANAGED_PROFILE_UID);
+ removeNetworkAndVerifySuccess();
+ }
+
+ /**
+ * Verifies that a background user is not allowed to remove a network.
+ */
+ @Test
+ public void removeNetworkAsOtherUser() throws Exception {
+ addNetworkAndVerifySuccess();
+ BinderUtil.setUid(OTHER_USER_UID);
+ removeNetworkAndVerifyFailure();
+ }
+
+ private void enableNetworkAndVerifySuccess() throws Exception {
+ when(mWifiNative.enableNetwork(0, true)).thenReturn(true);
+ assertTrue(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true));
+ wait(200);
+ verify(mWifiNative).enableNetwork(0, true);
+ }
+
+ private void enableNetworkAndVerifyFailure() throws Exception {
+ assertFalse(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true));
+ wait(200);
+ verify(mWifiNative, never()).enableNetwork(anyInt(), anyBoolean());
+ }
+
+ /**
+ * Verifies that the current foreground user is allowed to enable a network.
+ */
+ @Test
+ public void enableNetworkAsCurrentUser() throws Exception {
+ addNetworkAndVerifySuccess();
+ enableNetworkAndVerifySuccess();
+ }
+
+ /**
+ * Verifies that a managed profile of the current foreground user is allowed to enable a
+ * network.
+ */
+ @Test
+ public void enableNetworkAsCurrentUsersManagedProfile() throws Exception {
+ addNetworkAndVerifySuccess();
+ BinderUtil.setUid(MANAGED_PROFILE_UID);
+ enableNetworkAndVerifySuccess();
+ }
+
+ /**
+ * Verifies that a background user is not allowed to enable a network.
+ */
+ @Test
+ public void enableNetworkAsOtherUser() throws Exception {
+ addNetworkAndVerifySuccess();
+ BinderUtil.setUid(OTHER_USER_UID);
+ enableNetworkAndVerifyFailure();
+ }
+
+ private void forgetNetworkAndVerifySuccess() throws Exception {
+ when(mWifiNative.removeNetwork(0)).thenReturn(true);
+ final Message result =
+ mWsmAsyncChannel.sendMessageSynchronously(WifiManager.FORGET_NETWORK, 0);
+ assertEquals(WifiManager.FORGET_NETWORK_SUCCEEDED, result.what);
+ result.recycle();
+ wait(200);
+ assertTrue(mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).isEmpty());
+ }
+
+ private void forgetNetworkAndVerifyFailure() throws Exception {
+ final Message result =
+ mWsmAsyncChannel.sendMessageSynchronously(WifiManager.FORGET_NETWORK, 0);
+ assertEquals(WifiManager.FORGET_NETWORK_FAILED, result.what);
+ result.recycle();
+ wait(200);
+ assertEquals(1, mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).size());
+ verify(mWifiNative, never()).removeNetwork(anyInt());
+ }
+
+ /**
+ * Verifies that the current foreground user is allowed to forget a network.
+ */
+ @Test
+ public void forgetNetworkAsCurrentUser() throws Exception {
+ addNetworkAndVerifySuccess();
+ forgetNetworkAndVerifySuccess();
+ }
+
+ /**
+ * Verifies that a managed profile of the current foreground user is allowed to forget a
+ * network.
+ */
+ @Test
+ public void forgetNetworkAsCurrentUsersManagedProfile() throws Exception {
+ addNetworkAndVerifySuccess();
+ BinderUtil.setUid(MANAGED_PROFILE_UID);
+ forgetNetworkAndVerifySuccess();
+ }
+
+ /**
+ * Verifies that a background user is not allowed to forget a network.
+ */
+ @Test
+ public void forgetNetworkAsOtherUser() throws Exception {
+ addNetworkAndVerifySuccess();
+ BinderUtil.setUid(OTHER_USER_UID);
+ forgetNetworkAndVerifyFailure();
+ }
+
@Test
public void scan() throws Exception {
- addNetwork();
+ addNetworkAndVerifySuccess();
mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
@@ -539,7 +742,7 @@ public class WifiStateMachineTest {
@Test
public void connect() throws Exception {
- addNetwork();
+ addNetworkAndVerifySuccess();
mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
@@ -568,7 +771,7 @@ public class WifiStateMachineTest {
@Test
public void testDhcpFailure() throws Exception {
- addNetwork();
+ addNetworkAndVerifySuccess();
mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
@@ -592,7 +795,7 @@ public class WifiStateMachineTest {
@Test
public void testBadNetworkEvent() throws Exception {
- addNetwork();
+ addNetworkAndVerifySuccess();
mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
@@ -635,7 +838,7 @@ public class WifiStateMachineTest {
@Test
public void iconQueryTest() throws Exception {
/* enable wi-fi */
- addNetwork();
+ addNetworkAndVerifySuccess();
long bssid = 0x1234567800FFL;
String filename = "iconFileName.png";