First cut of user restriction layering.
- Start persisting restrictions set by DO/PO.
- Also dump user restrictions on dumpsys
- More changes will follow, including migration.
- Now System settings are mockable.
Bug 23902097
Bug 23902477
Change-Id: I0bda22f484e1a8e259a1feb2df83c5f4a29116da
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 31fc24b..341410d 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -59,8 +59,6 @@
import android.util.TimeUtils;
import android.util.Xml;
-import com.google.android.collect.Sets;
-
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IAppOpsService;
import com.android.internal.util.FastXmlSerializer;
@@ -82,7 +80,6 @@
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
-import java.util.Set;
import libcore.io.IoUtils;
@@ -147,10 +144,6 @@
*/
private static final boolean CONFIG_PROFILES_SHARE_CREDENTIAL = true;
- // Set of user restrictions, which can only be enforced by the system
- private static final Set<String> SYSTEM_CONTROLLED_RESTRICTIONS = Sets.newArraySet(
- UserManager.DISALLOW_RECORD_AUDIO);
-
static final int WRITE_USER_MSG = 1;
static final int WRITE_USER_DELAY = 2*1000; // 2 seconds
@@ -596,7 +589,7 @@
public void setUserRestriction(String key, boolean value, int userId) {
checkManageUsersPermission("setUserRestriction");
synchronized (mPackagesLock) {
- if (!SYSTEM_CONTROLLED_RESTRICTIONS.contains(key)) {
+ if (!UserRestrictionsUtils.SYSTEM_CONTROLLED_USER_RESTRICTIONS.contains(key)) {
Bundle restrictions = getUserRestrictions(userId);
restrictions.putBoolean(key, value);
setUserRestrictionsInternalLocked(restrictions, userId);
@@ -622,7 +615,7 @@
synchronized (mPackagesLock) {
final Bundle oldUserRestrictions = mUserRestrictions.get(userId);
// Restore the original state of system controlled restrictions from oldUserRestrictions
- for (String key : SYSTEM_CONTROLLED_RESTRICTIONS) {
+ for (String key : UserRestrictionsUtils.SYSTEM_CONTROLLED_USER_RESTRICTIONS) {
restrictions.remove(key);
if (oldUserRestrictions.containsKey(key)) {
restrictions.putBoolean(key, oldUserRestrictions.getBoolean(key));
@@ -815,7 +808,8 @@
&& type != XmlPullParser.END_TAG) {
if (type == XmlPullParser.START_TAG) {
if (parser.getName().equals(TAG_RESTRICTIONS)) {
- readRestrictionsLocked(parser, mGuestRestrictions);
+ UserRestrictionsUtils
+ .readRestrictions(parser, mGuestRestrictions);
}
break;
}
@@ -978,7 +972,7 @@
serializer.endTag(null, TAG_NAME);
Bundle restrictions = mUserRestrictions.get(userInfo.id);
if (restrictions != null) {
- writeRestrictionsLocked(serializer, restrictions);
+ UserRestrictionsUtils.writeRestrictions(serializer, restrictions, TAG_RESTRICTIONS);
}
serializer.endTag(null, TAG_USER);
@@ -1016,7 +1010,8 @@
serializer.attribute(null, ATTR_USER_VERSION, Integer.toString(mUserVersion));
serializer.startTag(null, TAG_GUEST_RESTRICTIONS);
- writeRestrictionsLocked(serializer, mGuestRestrictions);
+ UserRestrictionsUtils
+ .writeRestrictions(serializer, mGuestRestrictions, TAG_RESTRICTIONS);
serializer.endTag(null, TAG_GUEST_RESTRICTIONS);
final int userSize = mUsers.size();
for (int i = 0; i < userSize; i++) {
@@ -1036,45 +1031,6 @@
}
}
- private void writeRestrictionsLocked(XmlSerializer serializer, Bundle restrictions)
- throws IOException {
- serializer.startTag(null, TAG_RESTRICTIONS);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_WIFI);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_MODIFY_ACCOUNTS);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_INSTALL_APPS);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_UNINSTALL_APPS);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_SHARE_LOCATION);
- writeBoolean(serializer, restrictions,
- UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_BLUETOOTH);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_USB_FILE_TRANSFER);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_CREDENTIALS);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_REMOVE_USER);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_DEBUGGING_FEATURES);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_VPN);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_TETHERING);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_NETWORK_RESET);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_FACTORY_RESET);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_ADD_USER);
- writeBoolean(serializer, restrictions, UserManager.ENSURE_VERIFY_APPS);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_CELL_BROADCASTS);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_APPS_CONTROL);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_UNMUTE_MICROPHONE);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_ADJUST_VOLUME);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_OUTGOING_CALLS);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_SMS);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_FUN);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_CREATE_WINDOWS);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_OUTGOING_BEAM);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_WALLPAPER);
- writeBoolean(serializer, restrictions, UserManager.DISALLOW_SAFE_BOOT);
- writeBoolean(serializer, restrictions, UserManager.ALLOW_PARENT_PROFILE_APP_LINKING);
- serializer.endTag(null, TAG_RESTRICTIONS);
- }
-
private UserInfo readUserLocked(int id) {
int flags = 0;
int serialNumber = id;
@@ -1143,7 +1099,7 @@
name = parser.getText();
}
} else if (TAG_RESTRICTIONS.equals(tag)) {
- readRestrictionsLocked(parser, restrictions);
+ UserRestrictionsUtils.readRestrictions(parser, restrictions);
}
}
}
@@ -1172,60 +1128,6 @@
return null;
}
- private void readRestrictionsLocked(XmlPullParser parser, Bundle restrictions)
- throws IOException {
- readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_WIFI);
- readBoolean(parser, restrictions, UserManager.DISALLOW_MODIFY_ACCOUNTS);
- readBoolean(parser, restrictions, UserManager.DISALLOW_INSTALL_APPS);
- readBoolean(parser, restrictions, UserManager.DISALLOW_UNINSTALL_APPS);
- readBoolean(parser, restrictions, UserManager.DISALLOW_SHARE_LOCATION);
- readBoolean(parser, restrictions,
- UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
- readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_BLUETOOTH);
- readBoolean(parser, restrictions, UserManager.DISALLOW_USB_FILE_TRANSFER);
- readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_CREDENTIALS);
- readBoolean(parser, restrictions, UserManager.DISALLOW_REMOVE_USER);
- readBoolean(parser, restrictions, UserManager.DISALLOW_DEBUGGING_FEATURES);
- readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_VPN);
- readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_TETHERING);
- readBoolean(parser, restrictions, UserManager.DISALLOW_NETWORK_RESET);
- readBoolean(parser, restrictions, UserManager.DISALLOW_FACTORY_RESET);
- readBoolean(parser, restrictions, UserManager.DISALLOW_ADD_USER);
- readBoolean(parser, restrictions, UserManager.ENSURE_VERIFY_APPS);
- readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_CELL_BROADCASTS);
- readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
- readBoolean(parser, restrictions, UserManager.DISALLOW_APPS_CONTROL);
- readBoolean(parser, restrictions,
- UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
- readBoolean(parser, restrictions, UserManager.DISALLOW_UNMUTE_MICROPHONE);
- readBoolean(parser, restrictions, UserManager.DISALLOW_ADJUST_VOLUME);
- readBoolean(parser, restrictions, UserManager.DISALLOW_OUTGOING_CALLS);
- readBoolean(parser, restrictions, UserManager.DISALLOW_SMS);
- readBoolean(parser, restrictions, UserManager.DISALLOW_FUN);
- readBoolean(parser, restrictions, UserManager.DISALLOW_CREATE_WINDOWS);
- readBoolean(parser, restrictions, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE);
- readBoolean(parser, restrictions, UserManager.DISALLOW_OUTGOING_BEAM);
- readBoolean(parser, restrictions, UserManager.DISALLOW_WALLPAPER);
- readBoolean(parser, restrictions, UserManager.DISALLOW_SAFE_BOOT);
- readBoolean(parser, restrictions, UserManager.ALLOW_PARENT_PROFILE_APP_LINKING);
- }
-
- private void readBoolean(XmlPullParser parser, Bundle restrictions,
- String restrictionKey) {
- String value = parser.getAttributeValue(null, restrictionKey);
- if (value != null) {
- restrictions.putBoolean(restrictionKey, Boolean.parseBoolean(value));
- }
- }
-
- private void writeBoolean(XmlSerializer xml, Bundle restrictions, String restrictionKey)
- throws IOException {
- if (restrictions.containsKey(restrictionKey)) {
- xml.attribute(null, restrictionKey,
- Boolean.toString(restrictions.getBoolean(restrictionKey)));
- }
- }
-
private int readIntAttribute(XmlPullParser parser, String attr, int defaultValue) {
String valueString = parser.getAttributeValue(null, attr);
if (valueString == null) return defaultValue;
@@ -2142,7 +2044,13 @@
sb.append(" ago");
pw.println(sb);
}
+ pw.println(" Restrictions:");
+ UserRestrictionsUtils.dumpRestrictions(
+ pw, " ", mUserRestrictions.get(user.id));
}
+ pw.println();
+ pw.println("Guest restrictions:");
+ UserRestrictionsUtils.dumpRestrictions(pw, " ", mGuestRestrictions);
}
}
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
new file mode 100644
index 0000000..db1fd2e
--- /dev/null
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2015 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.pm;
+
+import com.google.android.collect.Sets;
+
+import com.android.internal.util.Preconditions;
+
+import android.os.Bundle;
+import android.os.UserManager;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Set;
+
+public class UserRestrictionsUtils {
+ private UserRestrictionsUtils() {
+ }
+
+ public static final String[] USER_RESTRICTIONS = {
+ UserManager.DISALLOW_CONFIG_WIFI,
+ UserManager.DISALLOW_MODIFY_ACCOUNTS,
+ UserManager.DISALLOW_INSTALL_APPS,
+ UserManager.DISALLOW_UNINSTALL_APPS,
+ UserManager.DISALLOW_SHARE_LOCATION,
+ UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
+ UserManager.DISALLOW_CONFIG_BLUETOOTH,
+ UserManager.DISALLOW_USB_FILE_TRANSFER,
+ UserManager.DISALLOW_CONFIG_CREDENTIALS,
+ UserManager.DISALLOW_REMOVE_USER,
+ UserManager.DISALLOW_DEBUGGING_FEATURES,
+ UserManager.DISALLOW_CONFIG_VPN,
+ UserManager.DISALLOW_CONFIG_TETHERING,
+ UserManager.DISALLOW_NETWORK_RESET,
+ UserManager.DISALLOW_FACTORY_RESET,
+ UserManager.DISALLOW_ADD_USER,
+ UserManager.ENSURE_VERIFY_APPS,
+ UserManager.DISALLOW_CONFIG_CELL_BROADCASTS,
+ UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,
+ UserManager.DISALLOW_APPS_CONTROL,
+ UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
+ UserManager.DISALLOW_UNMUTE_MICROPHONE,
+ UserManager.DISALLOW_ADJUST_VOLUME,
+ UserManager.DISALLOW_OUTGOING_CALLS,
+ UserManager.DISALLOW_SMS,
+ UserManager.DISALLOW_FUN,
+ UserManager.DISALLOW_CREATE_WINDOWS,
+ UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE,
+ UserManager.DISALLOW_OUTGOING_BEAM,
+ UserManager.DISALLOW_WALLPAPER,
+ UserManager.DISALLOW_SAFE_BOOT,
+ UserManager.ALLOW_PARENT_PROFILE_APP_LINKING,
+ UserManager.DISALLOW_RECORD_AUDIO,
+ };
+
+ /**
+ * Set of user restrictions, which can only be enforced by the system.
+ */
+ public static final Set<String> SYSTEM_CONTROLLED_USER_RESTRICTIONS = Sets.newArraySet(
+ UserManager.DISALLOW_RECORD_AUDIO);
+
+ /**
+ * Set of user restriction which we don't want to persist.
+ */
+ public static final Set<String> NON_PERSIST_USER_RESTRICTIONS = Sets.newArraySet(
+ UserManager.DISALLOW_RECORD_AUDIO);
+
+ public static void writeRestrictions(XmlSerializer serializer, Bundle restrictions,
+ String tag) throws IOException {
+ serializer.startTag(null, tag);
+ for (String key : USER_RESTRICTIONS) {
+ //
+ if (restrictions.getBoolean(key)
+ && !NON_PERSIST_USER_RESTRICTIONS.contains(key)) {
+ serializer.attribute(null, key, "true");
+ }
+ }
+ serializer.endTag(null, tag);
+ }
+
+ public static void readRestrictions(XmlPullParser parser, Bundle restrictions)
+ throws IOException {
+ for (String key : USER_RESTRICTIONS) {
+ final String value = parser.getAttributeValue(null, key);
+ if (value != null) {
+ restrictions.putBoolean(key, Boolean.parseBoolean(value));
+ }
+ }
+ }
+
+ public static void dumpRestrictions(PrintWriter pw, String prefix, Bundle restrictions) {
+ boolean noneSet = true;
+ if (restrictions != null) {
+ for (String key : restrictions.keySet()) {
+ if (restrictions.getBoolean(key, false)) {
+ pw.println(prefix + key);
+ noneSet = false;
+ }
+ }
+ }
+ if (noneSet) {
+ pw.println(prefix + "none");
+ }
+ }
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index e85f01a..cb5ab1b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -124,6 +124,7 @@
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo;
+import com.android.server.pm.UserRestrictionsUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -277,7 +278,8 @@
final LocalService mLocalService;
// Stores and loads state on device and profile owners.
- private final Owners mOwners;
+ @VisibleForTesting
+ final Owners mOwners;
private final Binder mToken = new Binder();
@@ -433,6 +435,8 @@
private static final String TAG_PROVIDER = "provider";
private static final String TAG_PACKAGE_LIST_ITEM = "item";
+ private static final String TAG_USER_RESTRICTIONS = "user-restrictions";
+
final DeviceAdminInfo info;
int passwordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
@@ -512,6 +516,8 @@
List<String> crossProfileWidgetProviders;
+ Bundle userRestrictions;
+
ActiveAdmin(DeviceAdminInfo _info) {
info = _info;
}
@@ -686,6 +692,10 @@
writePackageListToXml(out, TAG_PERMITTED_ACCESSIBILITY_SERVICES,
permittedAccessiblityServices);
writePackageListToXml(out, TAG_PERMITTED_IMES, permittedInputMethods);
+ if (hasUserRestrictions()) {
+ UserRestrictionsUtils.writeRestrictions(
+ out, userRestrictions, TAG_USER_RESTRICTIONS);
+ }
}
void writePackageListToXml(XmlSerializer out, String outerTag,
@@ -795,6 +805,8 @@
permittedAccessiblityServices = readPackageList(parser, tag);
} else if (TAG_PERMITTED_IMES.equals(tag)) {
permittedInputMethods = readPackageList(parser, tag);
+ } else if (TAG_USER_RESTRICTIONS.equals(tag)) {
+ UserRestrictionsUtils.readRestrictions(parser, ensureUserRestrictions());
} else {
Slog.w(LOG_TAG, "Unknown admin tag: " + tag);
XmlUtils.skipCurrentTag(parser);
@@ -915,6 +927,17 @@
return result;
}
+ boolean hasUserRestrictions() {
+ return userRestrictions != null && userRestrictions.size() > 0;
+ }
+
+ Bundle ensureUserRestrictions() {
+ if (userRestrictions == null) {
+ userRestrictions = new Bundle();
+ }
+ return userRestrictions;
+ }
+
void dump(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("uid="); pw.println(getUid());
pw.print(prefix); pw.println("policies:");
@@ -984,6 +1007,8 @@
pw.print(prefix); pw.print("permittedInputMethods=");
pw.println(permittedInputMethods.toString());
}
+ pw.print(prefix); pw.println("userRestrictions:");
+ UserRestrictionsUtils.dumpRestrictions(pw, prefix + " ", userRestrictions);
}
}
@@ -1116,6 +1141,10 @@
return getCallingUid() == Process.myUid();
}
+ final int userHandleGetCallingUserId() {
+ return UserHandle.getUserId(binderGetCallingUid());
+ }
+
File environmentGetUserSystemDirectory(int userId) {
return Environment.getUserSystemDirectory(userId);
}
@@ -1151,6 +1180,42 @@
String getDevicePolicyFilePathForSystemUser() {
return "/data/system/";
}
+
+ int settingsSecureGetIntForUser(String name, int def, int userHandle) {
+ return Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ name, def, userHandle);
+ }
+
+ void settingsSecurePutIntForUser(String name, int value, int userHandle) {
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ name, value, userHandle);
+ }
+
+ void settingsSecurePutStringForUser(String name, String value, int userHandle) {
+ Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ name, value, userHandle);
+ }
+
+ void settingsGlobalPutStringForUser(String name, String value, int userHandle) {
+ Settings.Global.putStringForUser(mContext.getContentResolver(),
+ name, value, userHandle);
+ }
+
+ void settingsSecurePutInt(String name, int value) {
+ Settings.Secure.putInt(mContext.getContentResolver(), name, value);
+ }
+
+ void settingsGlobalPutInt(String name, int value) {
+ Settings.Global.putInt(mContext.getContentResolver(), name, value);
+ }
+
+ void settingsSecurePutString(String name, String value) {
+ Settings.Secure.putString(mContext.getContentResolver(), name, value);
+ }
+
+ void settingsGlobalPutString(String name, String value) {
+ Settings.Global.putString(mContext.getContentResolver(), name, value);
+ }
}
/**
@@ -3158,8 +3223,7 @@
} else {
// Make sure KEEP_SCREEN_ON is disabled, since that
// would allow bypassing of the maximum time to lock.
- Settings.Global.putInt(mContext.getContentResolver(),
- Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0);
+ mInjector.settingsGlobalPutInt(Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0);
}
policy.mLastMaximumTimeToLock = timeMs;
@@ -3378,7 +3442,7 @@
// If there is a profile owner, redirect to that; otherwise query the device owner.
ComponentName aliasChooser = getProfileOwner(caller.getIdentifier());
if (aliasChooser == null && caller.isOwner()) {
- ActiveAdmin deviceOwnerAdmin = getDeviceOwnerAdmin();
+ ActiveAdmin deviceOwnerAdmin = getDeviceOwnerAdminLocked();
if (deviceOwnerAdmin != null) {
aliasChooser = deviceOwnerAdmin.info.getComponent();
}
@@ -3838,16 +3902,15 @@
} catch (NumberFormatException e) {}
}
exclusionList = exclusionList.trim();
- ContentResolver res = mContext.getContentResolver();
ProxyInfo proxyProperties = new ProxyInfo(data[0], proxyPort, exclusionList);
if (!proxyProperties.isValid()) {
Slog.e(LOG_TAG, "Invalid proxy properties, ignoring: " + proxyProperties.toString());
return;
}
- Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST, data[0]);
- Settings.Global.putInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, proxyPort);
- Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
+ mInjector.settingsGlobalPutString(Settings.Global.GLOBAL_HTTP_PROXY_HOST, data[0]);
+ mInjector.settingsGlobalPutInt(Settings.Global.GLOBAL_HTTP_PROXY_PORT, proxyPort);
+ mInjector.settingsGlobalPutString(Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
exclusionList);
}
@@ -4071,8 +4134,7 @@
if (required) {
long ident = mInjector.binderClearCallingIdentity();
try {
- Settings.Global.putInt(mContext.getContentResolver(),
- Settings.Global.AUTO_TIME, 1 /* AUTO_TIME on */);
+ mInjector.settingsGlobalPutInt(Settings.Global.AUTO_TIME, 1 /* AUTO_TIME on */);
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
@@ -4088,7 +4150,7 @@
return false;
}
synchronized (this) {
- ActiveAdmin deviceOwner = getDeviceOwnerAdmin();
+ ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
return (deviceOwner != null) ? deviceOwner.requireAutoTime : false;
}
}
@@ -4309,7 +4371,8 @@
}
// Returns the active device owner or null if there is no device owner.
- private ActiveAdmin getDeviceOwnerAdmin() {
+ @VisibleForTesting
+ ActiveAdmin getDeviceOwnerAdminLocked() {
String deviceOwnerPackageName = getDeviceOwner();
if (deviceOwnerPackageName == null) {
return null;
@@ -4502,7 +4565,8 @@
// Returns the active profile owner for this user or null if the current user has no
// profile owner.
- private ActiveAdmin getProfileOwnerAdmin(int userHandle) {
+ @VisibleForTesting
+ ActiveAdmin getProfileOwnerAdminLocked(int userHandle) {
ComponentName profileOwner = mOwners.getProfileOwnerComponent(userHandle);
if (profileOwner == null) {
return null;
@@ -5374,7 +5438,7 @@
@Override
public void setUserRestriction(ComponentName who, String key, boolean enabled) {
Preconditions.checkNotNull(who, "ComponentName is null");
- final int userHandle = UserHandle.getCallingUserId();
+ final int userHandle = mInjector.userHandleGetCallingUserId();
final UserHandle user = new UserHandle(userHandle);
synchronized (this) {
ActiveAdmin activeAdmin =
@@ -5399,37 +5463,40 @@
mInjector.getIAudioService()
.setMasterMute(true, 0, mContext.getPackageName(), userHandle);
} else if (UserManager.DISALLOW_CONFIG_WIFI.equals(key)) {
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ mInjector.settingsSecurePutIntForUser(
Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0,
userHandle);
} else if (UserManager.DISALLOW_SHARE_LOCATION.equals(key)) {
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ mInjector.settingsSecurePutIntForUser(
Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF,
userHandle);
- Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ mInjector.settingsSecurePutStringForUser(
Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "",
userHandle);
} else if (UserManager.DISALLOW_DEBUGGING_FEATURES.equals(key)) {
// Only disable adb if changing for system user, since it is global
// TODO: should this be admin user?
if (userHandle == UserHandle.USER_SYSTEM) {
- Settings.Global.putStringForUser(mContext.getContentResolver(),
+ mInjector.settingsGlobalPutStringForUser(
Settings.Global.ADB_ENABLED, "0", userHandle);
}
} else if (UserManager.ENSURE_VERIFY_APPS.equals(key)) {
- Settings.Global.putStringForUser(mContext.getContentResolver(),
+ mInjector.settingsGlobalPutStringForUser(
Settings.Global.PACKAGE_VERIFIER_ENABLE, "1",
userHandle);
- Settings.Global.putStringForUser(mContext.getContentResolver(),
+ mInjector.settingsGlobalPutStringForUser(
Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, "1",
userHandle);
} else if (UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES.equals(key)) {
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ mInjector.settingsSecurePutIntForUser(
Settings.Secure.INSTALL_NON_MARKET_APPS, 0,
userHandle);
}
}
mUserManager.setUserRestriction(key, enabled, user);
+ activeAdmin.ensureUserRestrictions().putBoolean(key, enabled);
+ saveSettingsLocked(userHandle);
+
if (enabled != alreadyRestricted) {
if (UserManager.DISALLOW_SHARE_LOCATION.equals(key)) {
// Send out notifications however as some clients may want to reread the
@@ -5730,7 +5797,7 @@
// TODO: Should there be a check to make sure this relationship is within a profile group?
//enforceSystemProcess("getCrossProfileCallerIdDisabled can only be called by system");
synchronized (this) {
- ActiveAdmin admin = getProfileOwnerAdmin(userId);
+ ActiveAdmin admin = getProfileOwnerAdminLocked(userId);
return (admin != null) ? admin.disableCallerId : false;
}
}
@@ -5823,7 +5890,7 @@
// within a profile group?
// enforceSystemProcess("getCrossProfileCallerIdDisabled can only be called by system");
synchronized (this) {
- ActiveAdmin admin = getProfileOwnerAdmin(userId);
+ ActiveAdmin admin = getProfileOwnerAdminLocked(userId);
return (admin != null) ? admin.disableBluetoothContactSharing : false;
}
}
@@ -5926,7 +5993,6 @@
@Override
public void setGlobalSetting(ComponentName who, String setting, String value) {
- final ContentResolver contentResolver = mContext.getContentResolver();
Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
@@ -5954,7 +6020,7 @@
long id = mInjector.binderClearCallingIdentity();
try {
- Settings.Global.putString(contentResolver, setting, value);
+ mInjector.settingsGlobalPutString(setting, value);
} finally {
mInjector.binderRestoreCallingIdentity(id);
}
@@ -5983,7 +6049,7 @@
long id = mInjector.binderClearCallingIdentity();
try {
- Settings.Secure.putStringForUser(contentResolver, setting, value, callingUserId);
+ mInjector.settingsSecurePutStringForUser(setting, value, callingUserId);
} finally {
mInjector.binderRestoreCallingIdentity(id);
}
@@ -6106,11 +6172,10 @@
*/
void updateUserSetupComplete() {
List<UserInfo> users = mUserManager.getUsers(true);
- ContentResolver resolver = mContext.getContentResolver();
final int N = users.size();
for (int i = 0; i < N; i++) {
int userHandle = users.get(i).id;
- if (Settings.Secure.getIntForUser(resolver, Settings.Secure.USER_SETUP_COMPLETE, 0,
+ if (mInjector.settingsSecureGetIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 0,
userHandle) != 0) {
DevicePolicyData policy = getUserData(userHandle);
if (!policy.mUserSetupComplete) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
index 76122e1..f9543c2 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
@@ -16,16 +16,11 @@
package com.android.server.devicepolicy;
-import android.app.AppGlobals;
import android.app.admin.SystemUpdatePolicy;
import android.content.ComponentName;
import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.os.Environment;
-import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArrayMap;
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index f4ffe2e..b109e7b 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -225,5 +225,45 @@
boolean userManagerIsSplitSystemUser() {
return context.userManagerForMock.isSplitSystemUser();
}
+
+ @Override
+ int settingsSecureGetIntForUser(String name, int def, int userHandle) {
+ return context.settings.settingsSecureGetIntForUser(name, def, userHandle);
+ }
+
+ @Override
+ void settingsSecurePutIntForUser(String name, int value, int userHandle) {
+ context.settings.settingsSecurePutIntForUser(name, value, userHandle);
+ }
+
+ @Override
+ void settingsSecurePutStringForUser(String name, String value, int userHandle) {
+ context.settings.settingsSecurePutStringForUser(name, value, userHandle);
+ }
+
+ @Override
+ void settingsGlobalPutStringForUser(String name, String value, int userHandle) {
+ context.settings.settingsGlobalPutStringForUser(name, value, userHandle);
+ }
+
+ @Override
+ void settingsSecurePutInt(String name, int value) {
+ context.settings.settingsSecurePutInt(name, value);
+ }
+
+ @Override
+ void settingsGlobalPutInt(String name, int value) {
+ context.settings.settingsGlobalPutInt(name, value);
+ }
+
+ @Override
+ void settingsSecurePutString(String name, String value) {
+ context.settings.settingsSecurePutString(name, value);
+ }
+
+ @Override
+ void settingsGlobalPutString(String name, String value) {
+ context.settings.settingsGlobalPutString(name, value);
+ }
}
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 5b23798..03b892e 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -31,8 +31,8 @@
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.content.pm.PackageInfo;
-import android.content.pm.UserInfo;
import android.os.UserHandle;
+import android.os.UserManager;
import android.util.Pair;
import org.mockito.ArgumentCaptor;
@@ -65,8 +65,6 @@
(mmma frameworks/base/services/tests/servicestests/ for non-ninja build)
*/
public class DevicePolicyManagerTest extends DpmTestBase {
-
-
private DpmMockContext mContext;
public DevicePolicyManager dpm;
public DevicePolicyManagerServiceTestable dpms;
@@ -207,9 +205,7 @@
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
- final UserInfo uh = new UserInfo(DpmMockContext.CALLER_USER_HANDLE, "user", 0);
-
- // DO needs to be an DA.
+ // PO needs to be an DA.
dpm.setActiveAdmin(admin, /* replace =*/ false);
// Fire!
@@ -625,4 +621,97 @@
dpm.setApplicationRestrictions(admin1, "pkg2", new Bundle());
assertEquals(0, dpm.getApplicationRestrictions(admin1, "pkg2").size());
}
+
+ public void testSetUserRestriction_asDo() throws Exception {
+ mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL);
+
+ // First, set DO.
+
+ // Call from a process on the system user.
+ mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+
+ // Make sure admin1 is installed on system user.
+ setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
+ setUpApplicationInfo(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED,
+ DpmMockContext.CALLER_SYSTEM_USER_UID);
+
+ // Call.
+ dpm.setActiveAdmin(admin1, /* replace =*/ false, UserHandle.USER_SYSTEM);
+ assertTrue(dpm.setDeviceOwner(admin1.getPackageName(), "owner-name",
+ UserHandle.USER_SYSTEM));
+
+ assertFalse(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
+ .getBoolean(UserManager.DISALLOW_SMS));
+ assertFalse(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
+ .getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
+
+ dpm.addUserRestriction(admin1, UserManager.DISALLOW_SMS);
+ dpm.addUserRestriction(admin1, UserManager.DISALLOW_OUTGOING_CALLS);
+
+ assertTrue(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
+ .getBoolean(UserManager.DISALLOW_SMS));
+ assertTrue(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
+ .getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
+
+ dpm.clearUserRestriction(admin1, UserManager.DISALLOW_SMS);
+
+ assertFalse(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
+ .getBoolean(UserManager.DISALLOW_SMS));
+ assertTrue(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
+ .getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
+
+ dpm.clearUserRestriction(admin1, UserManager.DISALLOW_OUTGOING_CALLS);
+
+ assertFalse(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
+ .getBoolean(UserManager.DISALLOW_SMS));
+ assertFalse(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
+ .getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
+
+ // TODO Check inner calls.
+ // TODO Make sure restrictions are written to the file.
+ }
+
+ public void testSetUserRestriction_asPo() {
+ setAsProfileOwner(admin1);
+
+ assertFalse(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
+ .ensureUserRestrictions()
+ .getBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES));
+ assertFalse(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
+ .ensureUserRestrictions()
+ .getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
+
+ dpm.addUserRestriction(admin1, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
+ dpm.addUserRestriction(admin1, UserManager.DISALLOW_OUTGOING_CALLS);
+
+ assertTrue(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
+ .ensureUserRestrictions()
+ .getBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES));
+ assertTrue(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
+ .ensureUserRestrictions()
+ .getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
+
+ dpm.clearUserRestriction(admin1, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
+
+ assertFalse(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
+ .ensureUserRestrictions()
+ .getBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES));
+ assertTrue(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
+ .ensureUserRestrictions()
+ .getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
+
+ dpm.clearUserRestriction(admin1, UserManager.DISALLOW_OUTGOING_CALLS);
+
+ assertFalse(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
+ .ensureUserRestrictions()
+ .getBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES));
+ assertFalse(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
+ .ensureUserRestrictions()
+ .getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
+
+ // TODO Check inner calls.
+ // TODO Make sure restrictions are written to the file.
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index 7b36e88..73d63ea 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -158,6 +158,33 @@
}
}
+ public static class SettingsForMock {
+ int settingsSecureGetIntForUser(String name, int def, int userHandle) {
+ return 0;
+ }
+
+ void settingsSecurePutIntForUser(String name, int value, int userHandle) {
+ }
+
+ void settingsSecurePutStringForUser(String name, String value, int userHandle) {
+ }
+
+ void settingsGlobalPutStringForUser(String name, String value, int userHandle) {
+ }
+
+ void settingsSecurePutInt(String name, int value) {
+ }
+
+ void settingsGlobalPutInt(String name, int value) {
+ }
+
+ void settingsSecurePutString(String name, String value) {
+ }
+
+ void settingsGlobalPutString(String name, String value) {
+ }
+ }
+
public final Context realTestContext;
/**
@@ -184,6 +211,7 @@
public final IBackupManager ibackupManager;
public final IAudioService iaudioService;
public final LockPatternUtils lockPatternUtils;
+ public final SettingsForMock settings;
/** Note this is a partial mock, not a real mock. */
public final PackageManager packageManager;
@@ -212,6 +240,7 @@
ibackupManager = mock(IBackupManager.class);
iaudioService = mock(IAudioService.class);
lockPatternUtils = mock(LockPatternUtils.class);
+ settings = mock(SettingsForMock.class);
// Package manager is huge, so we use a partial mock instead.
packageManager = spy(context.getPackageManager());
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
index 5255628..a210d46 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
@@ -21,6 +21,7 @@
import android.content.ComponentName;
import android.content.pm.UserInfo;
import android.os.UserHandle;
+import android.os.UserManager;
import android.util.Log;
import java.io.BufferedReader;
@@ -28,6 +29,8 @@
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.ArrayList;
import static org.mockito.Mockito.when;