Loading services/core/java/com/android/server/pm/RestrictionsSet.java 0 → 100644 +256 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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 android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.os.Bundle; import android.os.UserManager; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; /** * Data structure that contains the mapping of users to user restrictions (either the user * restrictions that apply to them, or the user restrictions that they set, depending on the * circumstances). * * @hide */ public class RestrictionsSet { private static final String USER_ID = "user_id"; private static final String TAG_RESTRICTIONS = "restrictions"; private static final String TAG_RESTRICTIONS_USER = "restrictions_user"; /** * Mapping of user restrictions. * Only non-empty restriction bundles are stored. * The key is the user id of the user. * userId -> restrictionBundle */ private final SparseArray<Bundle> mUserRestrictions = new SparseArray<>(0); public RestrictionsSet() { } public RestrictionsSet(@UserIdInt int userId, @NonNull Bundle restrictions) { if (restrictions.isEmpty()) { throw new IllegalArgumentException("empty restriction bundle cannot be added."); } mUserRestrictions.put(userId, restrictions); } /** * Updates restriction bundle for a given user. * If new bundle is empty, record is removed from the array. * * @return whether restrictions bundle is different from the old one. */ public boolean updateRestrictions(@UserIdInt int userId, @Nullable Bundle restrictions) { final boolean changed = !UserRestrictionsUtils.areEqual(mUserRestrictions.get(userId), restrictions); if (!changed) { return false; } if (!UserRestrictionsUtils.isEmpty(restrictions)) { mUserRestrictions.put(userId, restrictions); } else { mUserRestrictions.delete(userId); } return true; } /** * Moves a particular restriction from one restriction set to another, e.g. for all users. */ public void moveRestriction(@NonNull RestrictionsSet destRestrictions, String restriction) { for (int i = 0; i < mUserRestrictions.size(); i++) { final int userId = mUserRestrictions.keyAt(i); final Bundle from = mUserRestrictions.valueAt(i); if (UserRestrictionsUtils.contains(from, restriction)) { from.remove(restriction); Bundle to = destRestrictions.getRestrictions(userId); if (to == null) { to = new Bundle(); to.putBoolean(restriction, true); destRestrictions.updateRestrictions(userId, to); } else { to.putBoolean(restriction, true); } // Don't keep empty bundles. if (from.isEmpty()) { mUserRestrictions.removeAt(i); i--; } } } } /** * @return whether restrictions set has no restrictions. */ public boolean isEmpty() { return mUserRestrictions.size() == 0; } /** * Merge all restrictions in restrictions set into one bundle. The original user restrictions * set does not get modified, instead a new bundle is returned. * * @return restrictions bundle containing all user restrictions. */ public @NonNull Bundle mergeAll() { final Bundle result = new Bundle(); for (int i = 0; i < mUserRestrictions.size(); i++) { UserRestrictionsUtils.merge(result, mUserRestrictions.valueAt(i)); } return result; } /** * @return list of enforcing users that enforce a particular restriction. */ public @NonNull List<UserManager.EnforcingUser> getEnforcingUsers(String restriction, @UserIdInt int deviceOwnerUserId) { final List<UserManager.EnforcingUser> result = new ArrayList<>(); for (int i = 0; i < mUserRestrictions.size(); i++) { if (UserRestrictionsUtils.contains(mUserRestrictions.valueAt(i), restriction)) { result.add(getEnforcingUser(mUserRestrictions.keyAt(i), deviceOwnerUserId)); } } return result; } private UserManager.EnforcingUser getEnforcingUser(@UserIdInt int userId, @UserIdInt int deviceOwnerUserId) { int source = deviceOwnerUserId == userId ? UserManager.RESTRICTION_SOURCE_DEVICE_OWNER : UserManager.RESTRICTION_SOURCE_PROFILE_OWNER; return new UserManager.EnforcingUser(userId, source); } /** * @return list of user restrictions for a given user. Null is returned if the user does not * have any restrictions. */ public @Nullable Bundle getRestrictions(@UserIdInt int userId) { return mUserRestrictions.get(userId); } /** * Removes a given user from the restrictions set, returning true if the user has non-empty * restrictions before removal. */ public boolean remove(@UserIdInt int userId) { boolean hasUserRestriction = mUserRestrictions.contains(userId); mUserRestrictions.remove(userId); return hasUserRestriction; } /** * Remove list of users and user restrictions. */ public void removeAllRestrictions() { mUserRestrictions.clear(); } /** * Serialize a given {@link RestrictionsSet} to XML. */ public void writeRestrictions(@NonNull XmlSerializer serializer, @NonNull String outerTag) throws IOException { serializer.startTag(null, outerTag); for (int i = 0; i < mUserRestrictions.size(); i++) { serializer.startTag(null, TAG_RESTRICTIONS_USER); serializer.attribute(null, USER_ID, String.valueOf(mUserRestrictions.keyAt(i))); UserRestrictionsUtils.writeRestrictions(serializer, mUserRestrictions.valueAt(i), TAG_RESTRICTIONS); serializer.endTag(null, TAG_RESTRICTIONS_USER); } serializer.endTag(null, outerTag); } /** * Read restrictions from XML. */ public static RestrictionsSet readRestrictions(@NonNull XmlPullParser parser, @NonNull String outerTag) throws IOException, XmlPullParserException { RestrictionsSet restrictionsSet = new RestrictionsSet(); int userId = 0; int type; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { String tag = parser.getName(); if (type == XmlPullParser.END_TAG && outerTag.equals(tag)) { return restrictionsSet; } else if (type == XmlPullParser.START_TAG && TAG_RESTRICTIONS_USER.equals(tag)) { userId = Integer.parseInt(parser.getAttributeValue(null, USER_ID)); } else if (type == XmlPullParser.START_TAG && TAG_RESTRICTIONS.equals(tag)) { Bundle restrictions = UserRestrictionsUtils.readRestrictions(parser); restrictionsSet.updateRestrictions(userId, restrictions); } } throw new XmlPullParserException("restrictions cannot be read as xml is malformed."); } /** * Dumps {@link RestrictionsSet}. */ public void dumpRestrictions(PrintWriter pw, String prefix) { boolean noneSet = true; for (int i = 0; i < mUserRestrictions.size(); i++) { pw.println(prefix + "User Id: " + mUserRestrictions.keyAt(i)); UserRestrictionsUtils.dumpRestrictions(pw, prefix + " ", mUserRestrictions.valueAt(i)); noneSet = false; } if (noneSet) { pw.println(prefix + "none"); } } public boolean containsKey(@UserIdInt int userId) { return mUserRestrictions.contains(userId); } @VisibleForTesting public int size() { return mUserRestrictions.size(); } @VisibleForTesting public int keyAt(int index) { return mUserRestrictions.keyAt(index); } @VisibleForTesting public Bundle valueAt(int index) { return mUserRestrictions.valueAt(index); } } services/core/java/com/android/server/pm/UserManagerService.java +187 −91 File changed.Preview size limit exceeded, changes collapsed. Show changes services/core/java/com/android/server/pm/UserRestrictionsUtils.java +8 −36 Original line number Diff line number Diff line Loading @@ -394,22 +394,6 @@ public class UserRestrictionsUtils { } } /** * Merges a sparse array of restrictions bundles into one. */ @Nullable public static Bundle mergeAll(SparseArray<Bundle> restrictions) { if (restrictions.size() == 0) { return null; } else { final Bundle result = new Bundle(); for (int i = 0; i < restrictions.size(); i++) { merge(result, restrictions.valueAt(i)); } return result; } } /** * @return true if a restriction is settable by device owner. */ Loading Loading @@ -864,27 +848,15 @@ public class UserRestrictionsUtils { } /** * Moves a particular restriction from one array of bundles to another, e.g. for all users. * Moves a particular restriction from one array of restrictions sets to a restriction set, * e.g. for all users. */ public static void moveRestriction(String restrictionKey, SparseArray<Bundle> srcRestrictions, SparseArray<Bundle> destRestrictions) { for (int i = 0; i < srcRestrictions.size(); i++) { final int key = srcRestrictions.keyAt(i); final Bundle from = srcRestrictions.valueAt(i); if (contains(from, restrictionKey)) { from.remove(restrictionKey); Bundle to = destRestrictions.get(key); if (to == null) { to = new Bundle(); destRestrictions.append(key, to); } to.putBoolean(restrictionKey, true); // Don't keep empty bundles. if (from.isEmpty()) { srcRestrictions.removeAt(i); i--; } } public static void moveRestriction(String restrictionKey, SparseArray<RestrictionsSet> sourceRestrictionsSets, RestrictionsSet destRestrictionSet) { for (int i = 0; i < sourceRestrictionsSets.size(); i++) { final RestrictionsSet sourceRestrictionsSet = sourceRestrictionsSets.valueAt(i); sourceRestrictionsSet.moveRestriction(destRestrictionSet, restrictionKey); } } Loading services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java +20 −1 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ import android.test.AndroidTestCase; import android.util.Log; import android.util.Printer; import com.android.server.pm.RestrictionsSet; import libcore.io.Streams; import com.google.android.collect.Lists; Loading @@ -35,7 +37,6 @@ import org.junit.Assert; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; Loading @@ -58,6 +59,13 @@ public class DpmTestUtils extends AndroidTestCase { return list == null ? 0 : list.size(); } public static RestrictionsSet newRestrictions(int userId, String... restrictions) { Bundle localRestrictionsBundle = newRestrictions(restrictions); RestrictionsSet localRestrictions = new RestrictionsSet(); localRestrictions.updateRestrictions(userId, localRestrictionsBundle); return localRestrictions; } public static Bundle newRestrictions(String... restrictions) { final Bundle ret = new Bundle(); for (String restriction : restrictions) { Loading @@ -66,6 +74,17 @@ public class DpmTestUtils extends AndroidTestCase { return ret; } public static void assertRestrictions(RestrictionsSet expected, RestrictionsSet actual) { assertEquals(expected.size(), actual.size()); for (int i = 0; i < expected.size(); i++) { int originatingUserId = expected.keyAt(i); Bundle actualRestrictions = actual.getRestrictions(originatingUserId); assertFalse(actualRestrictions.isEmpty()); assertRestrictions(expected.getRestrictions(originatingUserId), actualRestrictions); } } public static void assertRestrictions(Bundle expected, Bundle actual) { final ArrayList<String> elist; if (expected == null) { Loading services/tests/servicestests/src/com/android/server/pm/RestrictionsSetTest.java 0 → 100644 +191 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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 static com.android.server.devicepolicy.DpmTestUtils.assertRestrictions; import static com.android.server.devicepolicy.DpmTestUtils.newRestrictions; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import android.os.Bundle; import android.os.UserHandle; import android.os.UserManager; import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; import java.util.List; /** Test for {@link RestrictionsSet}. */ @RunWith(AndroidJUnit4.class) public class RestrictionsSetTest { private RestrictionsSet mRestrictionsSet = new RestrictionsSet(); private final int originatingUserId = 0; @Test public void testUpdateRestrictions_addRestrictions() { Bundle restrictions = newRestrictions(UserManager.ENSURE_VERIFY_APPS); assertTrue(mRestrictionsSet.updateRestrictions(originatingUserId, restrictions)); assertRestrictions(restrictions, mRestrictionsSet.getRestrictions(originatingUserId)); } @Test public void testUpdateRestrictions_removeRestrictions() { Bundle restrictions = newRestrictions(UserManager.ENSURE_VERIFY_APPS); mRestrictionsSet.updateRestrictions(originatingUserId, restrictions); assertTrue(mRestrictionsSet.updateRestrictions(originatingUserId, new Bundle())); assertNull(mRestrictionsSet.getRestrictions(originatingUserId)); } @Test public void testUpdateRestrictions_noChange() { Bundle restrictions = newRestrictions(UserManager.ENSURE_VERIFY_APPS); mRestrictionsSet.updateRestrictions(originatingUserId, restrictions); assertFalse(mRestrictionsSet.updateRestrictions(originatingUserId, restrictions)); } @Test public void testMoveRestriction_containsRestriction() { RestrictionsSet destRestrictionsSet = new RestrictionsSet(); String restriction = UserManager.DISALLOW_CONFIG_DATE_TIME; mRestrictionsSet.updateRestrictions(originatingUserId, newRestrictions(restriction)); mRestrictionsSet.moveRestriction(destRestrictionsSet, restriction); assertNull(mRestrictionsSet.getRestrictions(originatingUserId)); assertNotNull(destRestrictionsSet.getRestrictions(originatingUserId)); assertRestrictions(newRestrictions(restriction), destRestrictionsSet.getRestrictions(originatingUserId)); } @Test public void testMoveRestriction_doesNotContainRestriction() { RestrictionsSet destRestrictionsSet = new RestrictionsSet(); mRestrictionsSet.updateRestrictions(originatingUserId, newRestrictions(UserManager.ENSURE_VERIFY_APPS)); mRestrictionsSet.moveRestriction(destRestrictionsSet, UserManager.DISALLOW_CONFIG_DATE_TIME); assertRestrictions(newRestrictions(UserManager.ENSURE_VERIFY_APPS), mRestrictionsSet.getRestrictions(originatingUserId)); assertNull(destRestrictionsSet.getRestrictions(originatingUserId)); } @Test public void testIsEmpty_noRestrictions() { assertTrue(mRestrictionsSet.isEmpty()); } @Test public void testIsEmpty_hasRestrictions() { mRestrictionsSet.updateRestrictions(originatingUserId, newRestrictions(UserManager.ENSURE_VERIFY_APPS, UserManager.DISALLOW_CONFIG_DATE_TIME)); assertFalse(mRestrictionsSet.isEmpty()); } @Test public void testMergeAll_noRestrictions() { assertTrue(mRestrictionsSet.mergeAll().isEmpty()); } @Test public void testMergeAll_hasRestrictions() { mRestrictionsSet.updateRestrictions(originatingUserId, newRestrictions(UserManager.ENSURE_VERIFY_APPS, UserManager.DISALLOW_CONFIG_DATE_TIME)); mRestrictionsSet.updateRestrictions(10, newRestrictions(UserManager.DISALLOW_ADD_USER, UserManager.DISALLOW_AIRPLANE_MODE)); Bundle actual = mRestrictionsSet.mergeAll(); assertRestrictions(newRestrictions(UserManager.ENSURE_VERIFY_APPS, UserManager.DISALLOW_CONFIG_DATE_TIME, UserManager.DISALLOW_ADD_USER, UserManager.DISALLOW_AIRPLANE_MODE), actual); } @Test public void testGetEnforcingUsers_hasEnforcingUser() { mRestrictionsSet.updateRestrictions(originatingUserId, newRestrictions(UserManager.ENSURE_VERIFY_APPS)); mRestrictionsSet.updateRestrictions(10, newRestrictions(UserManager.DISALLOW_ADD_USER)); List<UserManager.EnforcingUser> enforcingUsers = mRestrictionsSet.getEnforcingUsers( UserManager.ENSURE_VERIFY_APPS, originatingUserId); UserManager.EnforcingUser enforcingUser1 = enforcingUsers.get(0); assertEquals(UserHandle.of(originatingUserId), enforcingUser1.getUserHandle()); assertEquals(UserManager.RESTRICTION_SOURCE_DEVICE_OWNER, enforcingUser1.getUserRestrictionSource()); } @Test public void testGetEnforcingUsers_hasMultipleEnforcingUsers() { int originatingUserId2 = 10; mRestrictionsSet.updateRestrictions(originatingUserId, newRestrictions(UserManager.ENSURE_VERIFY_APPS)); mRestrictionsSet.updateRestrictions(originatingUserId2, newRestrictions(UserManager.ENSURE_VERIFY_APPS)); List<UserManager.EnforcingUser> enforcingUsers = mRestrictionsSet.getEnforcingUsers( UserManager.ENSURE_VERIFY_APPS, originatingUserId); assertEquals(2, enforcingUsers.size()); for (UserManager.EnforcingUser enforcingUser : enforcingUsers) { int userId = enforcingUser.getUserHandle().getIdentifier(); assertTrue((userId == originatingUserId) || (userId == originatingUserId2)); if (userId == originatingUserId) { assertEquals(UserManager.RESTRICTION_SOURCE_DEVICE_OWNER, enforcingUser.getUserRestrictionSource()); } if (userId == originatingUserId2) { assertEquals(UserManager.RESTRICTION_SOURCE_PROFILE_OWNER, enforcingUser.getUserRestrictionSource()); } } } @Test public void testGetEnforcingUsers_noEnforcingUsers() { mRestrictionsSet.updateRestrictions(originatingUserId, newRestrictions(UserManager.DISALLOW_USER_SWITCH)); List<UserManager.EnforcingUser> enforcingUsers = mRestrictionsSet.getEnforcingUsers( UserManager.ENSURE_VERIFY_APPS, originatingUserId); assertTrue(enforcingUsers.isEmpty()); } } Loading
services/core/java/com/android/server/pm/RestrictionsSet.java 0 → 100644 +256 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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 android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.os.Bundle; import android.os.UserManager; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; /** * Data structure that contains the mapping of users to user restrictions (either the user * restrictions that apply to them, or the user restrictions that they set, depending on the * circumstances). * * @hide */ public class RestrictionsSet { private static final String USER_ID = "user_id"; private static final String TAG_RESTRICTIONS = "restrictions"; private static final String TAG_RESTRICTIONS_USER = "restrictions_user"; /** * Mapping of user restrictions. * Only non-empty restriction bundles are stored. * The key is the user id of the user. * userId -> restrictionBundle */ private final SparseArray<Bundle> mUserRestrictions = new SparseArray<>(0); public RestrictionsSet() { } public RestrictionsSet(@UserIdInt int userId, @NonNull Bundle restrictions) { if (restrictions.isEmpty()) { throw new IllegalArgumentException("empty restriction bundle cannot be added."); } mUserRestrictions.put(userId, restrictions); } /** * Updates restriction bundle for a given user. * If new bundle is empty, record is removed from the array. * * @return whether restrictions bundle is different from the old one. */ public boolean updateRestrictions(@UserIdInt int userId, @Nullable Bundle restrictions) { final boolean changed = !UserRestrictionsUtils.areEqual(mUserRestrictions.get(userId), restrictions); if (!changed) { return false; } if (!UserRestrictionsUtils.isEmpty(restrictions)) { mUserRestrictions.put(userId, restrictions); } else { mUserRestrictions.delete(userId); } return true; } /** * Moves a particular restriction from one restriction set to another, e.g. for all users. */ public void moveRestriction(@NonNull RestrictionsSet destRestrictions, String restriction) { for (int i = 0; i < mUserRestrictions.size(); i++) { final int userId = mUserRestrictions.keyAt(i); final Bundle from = mUserRestrictions.valueAt(i); if (UserRestrictionsUtils.contains(from, restriction)) { from.remove(restriction); Bundle to = destRestrictions.getRestrictions(userId); if (to == null) { to = new Bundle(); to.putBoolean(restriction, true); destRestrictions.updateRestrictions(userId, to); } else { to.putBoolean(restriction, true); } // Don't keep empty bundles. if (from.isEmpty()) { mUserRestrictions.removeAt(i); i--; } } } } /** * @return whether restrictions set has no restrictions. */ public boolean isEmpty() { return mUserRestrictions.size() == 0; } /** * Merge all restrictions in restrictions set into one bundle. The original user restrictions * set does not get modified, instead a new bundle is returned. * * @return restrictions bundle containing all user restrictions. */ public @NonNull Bundle mergeAll() { final Bundle result = new Bundle(); for (int i = 0; i < mUserRestrictions.size(); i++) { UserRestrictionsUtils.merge(result, mUserRestrictions.valueAt(i)); } return result; } /** * @return list of enforcing users that enforce a particular restriction. */ public @NonNull List<UserManager.EnforcingUser> getEnforcingUsers(String restriction, @UserIdInt int deviceOwnerUserId) { final List<UserManager.EnforcingUser> result = new ArrayList<>(); for (int i = 0; i < mUserRestrictions.size(); i++) { if (UserRestrictionsUtils.contains(mUserRestrictions.valueAt(i), restriction)) { result.add(getEnforcingUser(mUserRestrictions.keyAt(i), deviceOwnerUserId)); } } return result; } private UserManager.EnforcingUser getEnforcingUser(@UserIdInt int userId, @UserIdInt int deviceOwnerUserId) { int source = deviceOwnerUserId == userId ? UserManager.RESTRICTION_SOURCE_DEVICE_OWNER : UserManager.RESTRICTION_SOURCE_PROFILE_OWNER; return new UserManager.EnforcingUser(userId, source); } /** * @return list of user restrictions for a given user. Null is returned if the user does not * have any restrictions. */ public @Nullable Bundle getRestrictions(@UserIdInt int userId) { return mUserRestrictions.get(userId); } /** * Removes a given user from the restrictions set, returning true if the user has non-empty * restrictions before removal. */ public boolean remove(@UserIdInt int userId) { boolean hasUserRestriction = mUserRestrictions.contains(userId); mUserRestrictions.remove(userId); return hasUserRestriction; } /** * Remove list of users and user restrictions. */ public void removeAllRestrictions() { mUserRestrictions.clear(); } /** * Serialize a given {@link RestrictionsSet} to XML. */ public void writeRestrictions(@NonNull XmlSerializer serializer, @NonNull String outerTag) throws IOException { serializer.startTag(null, outerTag); for (int i = 0; i < mUserRestrictions.size(); i++) { serializer.startTag(null, TAG_RESTRICTIONS_USER); serializer.attribute(null, USER_ID, String.valueOf(mUserRestrictions.keyAt(i))); UserRestrictionsUtils.writeRestrictions(serializer, mUserRestrictions.valueAt(i), TAG_RESTRICTIONS); serializer.endTag(null, TAG_RESTRICTIONS_USER); } serializer.endTag(null, outerTag); } /** * Read restrictions from XML. */ public static RestrictionsSet readRestrictions(@NonNull XmlPullParser parser, @NonNull String outerTag) throws IOException, XmlPullParserException { RestrictionsSet restrictionsSet = new RestrictionsSet(); int userId = 0; int type; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { String tag = parser.getName(); if (type == XmlPullParser.END_TAG && outerTag.equals(tag)) { return restrictionsSet; } else if (type == XmlPullParser.START_TAG && TAG_RESTRICTIONS_USER.equals(tag)) { userId = Integer.parseInt(parser.getAttributeValue(null, USER_ID)); } else if (type == XmlPullParser.START_TAG && TAG_RESTRICTIONS.equals(tag)) { Bundle restrictions = UserRestrictionsUtils.readRestrictions(parser); restrictionsSet.updateRestrictions(userId, restrictions); } } throw new XmlPullParserException("restrictions cannot be read as xml is malformed."); } /** * Dumps {@link RestrictionsSet}. */ public void dumpRestrictions(PrintWriter pw, String prefix) { boolean noneSet = true; for (int i = 0; i < mUserRestrictions.size(); i++) { pw.println(prefix + "User Id: " + mUserRestrictions.keyAt(i)); UserRestrictionsUtils.dumpRestrictions(pw, prefix + " ", mUserRestrictions.valueAt(i)); noneSet = false; } if (noneSet) { pw.println(prefix + "none"); } } public boolean containsKey(@UserIdInt int userId) { return mUserRestrictions.contains(userId); } @VisibleForTesting public int size() { return mUserRestrictions.size(); } @VisibleForTesting public int keyAt(int index) { return mUserRestrictions.keyAt(index); } @VisibleForTesting public Bundle valueAt(int index) { return mUserRestrictions.valueAt(index); } }
services/core/java/com/android/server/pm/UserManagerService.java +187 −91 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/core/java/com/android/server/pm/UserRestrictionsUtils.java +8 −36 Original line number Diff line number Diff line Loading @@ -394,22 +394,6 @@ public class UserRestrictionsUtils { } } /** * Merges a sparse array of restrictions bundles into one. */ @Nullable public static Bundle mergeAll(SparseArray<Bundle> restrictions) { if (restrictions.size() == 0) { return null; } else { final Bundle result = new Bundle(); for (int i = 0; i < restrictions.size(); i++) { merge(result, restrictions.valueAt(i)); } return result; } } /** * @return true if a restriction is settable by device owner. */ Loading Loading @@ -864,27 +848,15 @@ public class UserRestrictionsUtils { } /** * Moves a particular restriction from one array of bundles to another, e.g. for all users. * Moves a particular restriction from one array of restrictions sets to a restriction set, * e.g. for all users. */ public static void moveRestriction(String restrictionKey, SparseArray<Bundle> srcRestrictions, SparseArray<Bundle> destRestrictions) { for (int i = 0; i < srcRestrictions.size(); i++) { final int key = srcRestrictions.keyAt(i); final Bundle from = srcRestrictions.valueAt(i); if (contains(from, restrictionKey)) { from.remove(restrictionKey); Bundle to = destRestrictions.get(key); if (to == null) { to = new Bundle(); destRestrictions.append(key, to); } to.putBoolean(restrictionKey, true); // Don't keep empty bundles. if (from.isEmpty()) { srcRestrictions.removeAt(i); i--; } } public static void moveRestriction(String restrictionKey, SparseArray<RestrictionsSet> sourceRestrictionsSets, RestrictionsSet destRestrictionSet) { for (int i = 0; i < sourceRestrictionsSets.size(); i++) { final RestrictionsSet sourceRestrictionsSet = sourceRestrictionsSets.valueAt(i); sourceRestrictionsSet.moveRestriction(destRestrictionSet, restrictionKey); } } Loading
services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java +20 −1 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ import android.test.AndroidTestCase; import android.util.Log; import android.util.Printer; import com.android.server.pm.RestrictionsSet; import libcore.io.Streams; import com.google.android.collect.Lists; Loading @@ -35,7 +37,6 @@ import org.junit.Assert; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; Loading @@ -58,6 +59,13 @@ public class DpmTestUtils extends AndroidTestCase { return list == null ? 0 : list.size(); } public static RestrictionsSet newRestrictions(int userId, String... restrictions) { Bundle localRestrictionsBundle = newRestrictions(restrictions); RestrictionsSet localRestrictions = new RestrictionsSet(); localRestrictions.updateRestrictions(userId, localRestrictionsBundle); return localRestrictions; } public static Bundle newRestrictions(String... restrictions) { final Bundle ret = new Bundle(); for (String restriction : restrictions) { Loading @@ -66,6 +74,17 @@ public class DpmTestUtils extends AndroidTestCase { return ret; } public static void assertRestrictions(RestrictionsSet expected, RestrictionsSet actual) { assertEquals(expected.size(), actual.size()); for (int i = 0; i < expected.size(); i++) { int originatingUserId = expected.keyAt(i); Bundle actualRestrictions = actual.getRestrictions(originatingUserId); assertFalse(actualRestrictions.isEmpty()); assertRestrictions(expected.getRestrictions(originatingUserId), actualRestrictions); } } public static void assertRestrictions(Bundle expected, Bundle actual) { final ArrayList<String> elist; if (expected == null) { Loading
services/tests/servicestests/src/com/android/server/pm/RestrictionsSetTest.java 0 → 100644 +191 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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 static com.android.server.devicepolicy.DpmTestUtils.assertRestrictions; import static com.android.server.devicepolicy.DpmTestUtils.newRestrictions; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import android.os.Bundle; import android.os.UserHandle; import android.os.UserManager; import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; import java.util.List; /** Test for {@link RestrictionsSet}. */ @RunWith(AndroidJUnit4.class) public class RestrictionsSetTest { private RestrictionsSet mRestrictionsSet = new RestrictionsSet(); private final int originatingUserId = 0; @Test public void testUpdateRestrictions_addRestrictions() { Bundle restrictions = newRestrictions(UserManager.ENSURE_VERIFY_APPS); assertTrue(mRestrictionsSet.updateRestrictions(originatingUserId, restrictions)); assertRestrictions(restrictions, mRestrictionsSet.getRestrictions(originatingUserId)); } @Test public void testUpdateRestrictions_removeRestrictions() { Bundle restrictions = newRestrictions(UserManager.ENSURE_VERIFY_APPS); mRestrictionsSet.updateRestrictions(originatingUserId, restrictions); assertTrue(mRestrictionsSet.updateRestrictions(originatingUserId, new Bundle())); assertNull(mRestrictionsSet.getRestrictions(originatingUserId)); } @Test public void testUpdateRestrictions_noChange() { Bundle restrictions = newRestrictions(UserManager.ENSURE_VERIFY_APPS); mRestrictionsSet.updateRestrictions(originatingUserId, restrictions); assertFalse(mRestrictionsSet.updateRestrictions(originatingUserId, restrictions)); } @Test public void testMoveRestriction_containsRestriction() { RestrictionsSet destRestrictionsSet = new RestrictionsSet(); String restriction = UserManager.DISALLOW_CONFIG_DATE_TIME; mRestrictionsSet.updateRestrictions(originatingUserId, newRestrictions(restriction)); mRestrictionsSet.moveRestriction(destRestrictionsSet, restriction); assertNull(mRestrictionsSet.getRestrictions(originatingUserId)); assertNotNull(destRestrictionsSet.getRestrictions(originatingUserId)); assertRestrictions(newRestrictions(restriction), destRestrictionsSet.getRestrictions(originatingUserId)); } @Test public void testMoveRestriction_doesNotContainRestriction() { RestrictionsSet destRestrictionsSet = new RestrictionsSet(); mRestrictionsSet.updateRestrictions(originatingUserId, newRestrictions(UserManager.ENSURE_VERIFY_APPS)); mRestrictionsSet.moveRestriction(destRestrictionsSet, UserManager.DISALLOW_CONFIG_DATE_TIME); assertRestrictions(newRestrictions(UserManager.ENSURE_VERIFY_APPS), mRestrictionsSet.getRestrictions(originatingUserId)); assertNull(destRestrictionsSet.getRestrictions(originatingUserId)); } @Test public void testIsEmpty_noRestrictions() { assertTrue(mRestrictionsSet.isEmpty()); } @Test public void testIsEmpty_hasRestrictions() { mRestrictionsSet.updateRestrictions(originatingUserId, newRestrictions(UserManager.ENSURE_VERIFY_APPS, UserManager.DISALLOW_CONFIG_DATE_TIME)); assertFalse(mRestrictionsSet.isEmpty()); } @Test public void testMergeAll_noRestrictions() { assertTrue(mRestrictionsSet.mergeAll().isEmpty()); } @Test public void testMergeAll_hasRestrictions() { mRestrictionsSet.updateRestrictions(originatingUserId, newRestrictions(UserManager.ENSURE_VERIFY_APPS, UserManager.DISALLOW_CONFIG_DATE_TIME)); mRestrictionsSet.updateRestrictions(10, newRestrictions(UserManager.DISALLOW_ADD_USER, UserManager.DISALLOW_AIRPLANE_MODE)); Bundle actual = mRestrictionsSet.mergeAll(); assertRestrictions(newRestrictions(UserManager.ENSURE_VERIFY_APPS, UserManager.DISALLOW_CONFIG_DATE_TIME, UserManager.DISALLOW_ADD_USER, UserManager.DISALLOW_AIRPLANE_MODE), actual); } @Test public void testGetEnforcingUsers_hasEnforcingUser() { mRestrictionsSet.updateRestrictions(originatingUserId, newRestrictions(UserManager.ENSURE_VERIFY_APPS)); mRestrictionsSet.updateRestrictions(10, newRestrictions(UserManager.DISALLOW_ADD_USER)); List<UserManager.EnforcingUser> enforcingUsers = mRestrictionsSet.getEnforcingUsers( UserManager.ENSURE_VERIFY_APPS, originatingUserId); UserManager.EnforcingUser enforcingUser1 = enforcingUsers.get(0); assertEquals(UserHandle.of(originatingUserId), enforcingUser1.getUserHandle()); assertEquals(UserManager.RESTRICTION_SOURCE_DEVICE_OWNER, enforcingUser1.getUserRestrictionSource()); } @Test public void testGetEnforcingUsers_hasMultipleEnforcingUsers() { int originatingUserId2 = 10; mRestrictionsSet.updateRestrictions(originatingUserId, newRestrictions(UserManager.ENSURE_VERIFY_APPS)); mRestrictionsSet.updateRestrictions(originatingUserId2, newRestrictions(UserManager.ENSURE_VERIFY_APPS)); List<UserManager.EnforcingUser> enforcingUsers = mRestrictionsSet.getEnforcingUsers( UserManager.ENSURE_VERIFY_APPS, originatingUserId); assertEquals(2, enforcingUsers.size()); for (UserManager.EnforcingUser enforcingUser : enforcingUsers) { int userId = enforcingUser.getUserHandle().getIdentifier(); assertTrue((userId == originatingUserId) || (userId == originatingUserId2)); if (userId == originatingUserId) { assertEquals(UserManager.RESTRICTION_SOURCE_DEVICE_OWNER, enforcingUser.getUserRestrictionSource()); } if (userId == originatingUserId2) { assertEquals(UserManager.RESTRICTION_SOURCE_PROFILE_OWNER, enforcingUser.getUserRestrictionSource()); } } } @Test public void testGetEnforcingUsers_noEnforcingUsers() { mRestrictionsSet.updateRestrictions(originatingUserId, newRestrictions(UserManager.DISALLOW_USER_SWITCH)); List<UserManager.EnforcingUser> enforcingUsers = mRestrictionsSet.getEnforcingUsers( UserManager.ENSURE_VERIFY_APPS, originatingUserId); assertTrue(enforcingUsers.isEmpty()); } }