Loading core/java/android/app/admin/DevicePolicyManager.java +15 −8 Original line number Diff line number Diff line Loading @@ -6073,20 +6073,24 @@ public class DevicePolicyManager { /** * Sets which packages may enter lock task mode. * <p> * Any packages that shares uid with an allowed package will also be allowed to activate lock * Any packages that share uid with an allowed package will also be allowed to activate lock * task. From {@link android.os.Build.VERSION_CODES#M} removing packages from the lock task * package list results in locked tasks belonging to those packages to be finished. This * function can only be called by the device owner. * package list results in locked tasks belonging to those packages to be finished. * <p> * This function can only be called by the device owner or by a profile owner of a user/profile * that is affiliated with the device owner user. See {@link #setAffiliationIds}. Any packages * set via this method will be cleared if the user becomes unaffiliated. * * @param packages The list of packages allowed to enter lock task mode * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @throws SecurityException if {@code admin} is not a device owner. * @throws SecurityException if {@code admin} is not the device owner, or the profile owner of * an affiliated user or profile. * @see Activity#startLockTask() * @see DeviceAdminReceiver#onLockTaskModeEntering(Context, Intent, String) * @see DeviceAdminReceiver#onLockTaskModeExiting(Context, Intent) * @see UserManager#DISALLOW_CREATE_WINDOWS */ public void setLockTaskPackages(@NonNull ComponentName admin, String[] packages) public void setLockTaskPackages(@NonNull ComponentName admin, @NonNull String[] packages) throws SecurityException { throwIfParentInstance("setLockTaskPackages"); if (mService != null) { Loading @@ -6099,9 +6103,12 @@ public class DevicePolicyManager { } /** * This function returns the list of packages allowed to start the lock task mode. * Returns the list of packages allowed to start the lock task mode. * * @throws SecurityException if {@code admin} is not the device owner, or the profile owner of * an affiliated user or profile. * @see #setLockTaskPackages * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @hide */ public @NonNull String[] getLockTaskPackages(@NonNull ComponentName admin) { Loading @@ -6113,7 +6120,7 @@ public class DevicePolicyManager { throw e.rethrowFromSystemServer(); } } return null; return new String[0]; } /** Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +32 −35 Original line number Diff line number Diff line Loading @@ -8564,18 +8564,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } /** * Sets which packages may enter lock task mode. * * <p>This function can only be called by the device owner or alternatively by the profile owner * in case the user is affiliated. * * @param packages The list of packages allowed to enter lock task mode. */ @Override public void setLockTaskPackages(ComponentName who, String[] packages) throws SecurityException { Preconditions.checkNotNull(who, "ComponentName is null"); Preconditions.checkNotNull(packages, "packages is null"); synchronized (this) { getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); Loading @@ -8598,49 +8591,52 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { updateLockTaskPackagesLocked(packages, userHandle); } private void maybeClearLockTaskPackagesLocked() { final long ident = mInjector.binderClearCallingIdentity(); try { final List<UserInfo> userInfos = mUserManager.getUsers(/*excludeDying=*/ true); for (int i = 0; i < userInfos.size(); i++) { int userId = userInfos.get(i).id; final List<String> lockTaskPackages = getUserData(userId).mLockTaskPackages; if (!lockTaskPackages.isEmpty() && !isUserAffiliatedWithDeviceLocked(userId)) { Slog.d(LOG_TAG, "User id " + userId + " not affiliated. Clearing lock task packages"); setLockTaskPackagesLocked(userId, Collections.<String>emptyList()); } } } finally { mInjector.binderRestoreCallingIdentity(ident); } } /** * This function returns the list of components allowed to start the task lock mode. */ @Override public String[] getLockTaskPackages(ComponentName who) { Preconditions.checkNotNull(who, "ComponentName is null"); final int userHandle = mInjector.binderGetCallingUserHandle().getIdentifier(); synchronized (this) { getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); int userHandle = mInjector.binderGetCallingUserHandle().getIdentifier(); final List<String> packages = getLockTaskPackagesLocked(userHandle); return packages.toArray(new String[packages.size()]); } getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); if (!isUserAffiliatedWithDeviceLocked(userHandle)) { throw new SecurityException("Admin " + who + " is neither the device owner or affiliated user's profile owner."); } private List<String> getLockTaskPackagesLocked(int userHandle) { final DevicePolicyData policy = getUserData(userHandle); return policy.mLockTaskPackages; final List<String> packages = getUserData(userHandle).mLockTaskPackages; return packages.toArray(new String[packages.size()]); } } /** * This function lets the caller know whether the given package is allowed to start the * lock task mode. * @param pkg The package to check */ @Override public boolean isLockTaskPermitted(String pkg) { // Get current user's devicepolicy int uid = mInjector.binderGetCallingUid(); int userHandle = UserHandle.getUserId(uid); DevicePolicyData policy = getUserData(userHandle); final int userHandle = mInjector.userHandleGetCallingUserId(); synchronized (this) { for (int i = 0; i < policy.mLockTaskPackages.size(); i++) { String lockTaskPackage = policy.mLockTaskPackages.get(i); // If the given package equals one of the packages stored our list, // we allow this package to start lock task mode. if (lockTaskPackage.equals(pkg)) { return true; } return getUserData(userHandle).mLockTaskPackages.contains(pkg); } } return false; } @Override public void notifyLockTaskModeChanged(boolean isEnabled, String pkg, int userHandle) { Loading Loading @@ -9848,6 +9844,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // but as a result of that other users might become affiliated or un-affiliated. maybePauseDeviceWideLoggingLocked(); maybeResumeDeviceWideLoggingLocked(); maybeClearLockTaskPackagesLocked(); } } Loading services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +69 −0 Original line number Diff line number Diff line Loading @@ -3332,6 +3332,75 @@ public class DevicePolicyManagerTest extends DpmTestBase { MoreAsserts.assertEmpty(targetUsers); } public void testLockTaskPackagesAllowedForAffiliatedUsers() throws Exception { // Setup a device owner. mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; setupDeviceOwner(); // Lock task packages are updated when loading user data. verify(mContext.iactivityManager) .updateLockTaskPackages(eq(UserHandle.USER_SYSTEM), eq(new String[0])); // Set up a managed profile managed by different package (package name shouldn't matter) final int MANAGED_PROFILE_USER_ID = 15; final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(MANAGED_PROFILE_USER_ID, 20456); final ComponentName adminDifferentPackage = new ComponentName("another.package", "whatever.class"); addManagedProfile(adminDifferentPackage, MANAGED_PROFILE_ADMIN_UID, admin2); verify(mContext.iactivityManager) .updateLockTaskPackages(eq(MANAGED_PROFILE_USER_ID), eq(new String[0])); // The DO can still set lock task packages mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; final String[] doPackages = {"doPackage1", "doPackage2"}; dpm.setLockTaskPackages(admin1, doPackages); MoreAsserts.assertEquals(doPackages, dpm.getLockTaskPackages(admin1)); assertTrue(dpm.isLockTaskPermitted("doPackage1")); assertFalse(dpm.isLockTaskPermitted("anotherPackage")); verify(mContext.iactivityManager) .updateLockTaskPackages(eq(UserHandle.USER_SYSTEM), eq(doPackages)); // Managed profile is unaffiliated - shouldn't be able to setLockTaskPackages. mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID; final String[] poPackages = {"poPackage1", "poPackage2"}; try { dpm.setLockTaskPackages(adminDifferentPackage, poPackages); fail("Didn't throw expected security exception."); } catch (SecurityException expected) { } try { dpm.getLockTaskPackages(adminDifferentPackage); fail("Didn't throw expected security exception."); } catch (SecurityException expected) { } assertFalse(dpm.isLockTaskPermitted("doPackage1")); // Setting same affiliation ids final List<String> userAffiliationIds = Arrays.asList("some-affiliation-id"); mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; dpm.setAffiliationIds(admin1, userAffiliationIds); mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID; dpm.setAffiliationIds(adminDifferentPackage, userAffiliationIds); // Now the managed profile can set lock task packages. dpm.setLockTaskPackages(adminDifferentPackage, poPackages); MoreAsserts.assertEquals(poPackages, dpm.getLockTaskPackages(adminDifferentPackage)); assertTrue(dpm.isLockTaskPermitted("poPackage1")); assertFalse(dpm.isLockTaskPermitted("doPackage2")); verify(mContext.iactivityManager) .updateLockTaskPackages(eq(MANAGED_PROFILE_USER_ID), eq(poPackages)); // Unaffiliate the profile, lock task mode no longer available on the profile. dpm.setAffiliationIds(adminDifferentPackage, Collections.<String>emptyList()); assertFalse(dpm.isLockTaskPermitted("poPackage1")); // Lock task packages cleared when loading user data and when the user becomes unaffiliated. verify(mContext.iactivityManager, times(2)) .updateLockTaskPackages(eq(MANAGED_PROFILE_USER_ID), eq(new String[0])); mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; assertTrue(dpm.isLockTaskPermitted("doPackage1")); } public void testIsDeviceManaged() throws Exception { mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; setupDeviceOwner(); Loading Loading
core/java/android/app/admin/DevicePolicyManager.java +15 −8 Original line number Diff line number Diff line Loading @@ -6073,20 +6073,24 @@ public class DevicePolicyManager { /** * Sets which packages may enter lock task mode. * <p> * Any packages that shares uid with an allowed package will also be allowed to activate lock * Any packages that share uid with an allowed package will also be allowed to activate lock * task. From {@link android.os.Build.VERSION_CODES#M} removing packages from the lock task * package list results in locked tasks belonging to those packages to be finished. This * function can only be called by the device owner. * package list results in locked tasks belonging to those packages to be finished. * <p> * This function can only be called by the device owner or by a profile owner of a user/profile * that is affiliated with the device owner user. See {@link #setAffiliationIds}. Any packages * set via this method will be cleared if the user becomes unaffiliated. * * @param packages The list of packages allowed to enter lock task mode * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @throws SecurityException if {@code admin} is not a device owner. * @throws SecurityException if {@code admin} is not the device owner, or the profile owner of * an affiliated user or profile. * @see Activity#startLockTask() * @see DeviceAdminReceiver#onLockTaskModeEntering(Context, Intent, String) * @see DeviceAdminReceiver#onLockTaskModeExiting(Context, Intent) * @see UserManager#DISALLOW_CREATE_WINDOWS */ public void setLockTaskPackages(@NonNull ComponentName admin, String[] packages) public void setLockTaskPackages(@NonNull ComponentName admin, @NonNull String[] packages) throws SecurityException { throwIfParentInstance("setLockTaskPackages"); if (mService != null) { Loading @@ -6099,9 +6103,12 @@ public class DevicePolicyManager { } /** * This function returns the list of packages allowed to start the lock task mode. * Returns the list of packages allowed to start the lock task mode. * * @throws SecurityException if {@code admin} is not the device owner, or the profile owner of * an affiliated user or profile. * @see #setLockTaskPackages * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @hide */ public @NonNull String[] getLockTaskPackages(@NonNull ComponentName admin) { Loading @@ -6113,7 +6120,7 @@ public class DevicePolicyManager { throw e.rethrowFromSystemServer(); } } return null; return new String[0]; } /** Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +32 −35 Original line number Diff line number Diff line Loading @@ -8564,18 +8564,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } /** * Sets which packages may enter lock task mode. * * <p>This function can only be called by the device owner or alternatively by the profile owner * in case the user is affiliated. * * @param packages The list of packages allowed to enter lock task mode. */ @Override public void setLockTaskPackages(ComponentName who, String[] packages) throws SecurityException { Preconditions.checkNotNull(who, "ComponentName is null"); Preconditions.checkNotNull(packages, "packages is null"); synchronized (this) { getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); Loading @@ -8598,49 +8591,52 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { updateLockTaskPackagesLocked(packages, userHandle); } private void maybeClearLockTaskPackagesLocked() { final long ident = mInjector.binderClearCallingIdentity(); try { final List<UserInfo> userInfos = mUserManager.getUsers(/*excludeDying=*/ true); for (int i = 0; i < userInfos.size(); i++) { int userId = userInfos.get(i).id; final List<String> lockTaskPackages = getUserData(userId).mLockTaskPackages; if (!lockTaskPackages.isEmpty() && !isUserAffiliatedWithDeviceLocked(userId)) { Slog.d(LOG_TAG, "User id " + userId + " not affiliated. Clearing lock task packages"); setLockTaskPackagesLocked(userId, Collections.<String>emptyList()); } } } finally { mInjector.binderRestoreCallingIdentity(ident); } } /** * This function returns the list of components allowed to start the task lock mode. */ @Override public String[] getLockTaskPackages(ComponentName who) { Preconditions.checkNotNull(who, "ComponentName is null"); final int userHandle = mInjector.binderGetCallingUserHandle().getIdentifier(); synchronized (this) { getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); int userHandle = mInjector.binderGetCallingUserHandle().getIdentifier(); final List<String> packages = getLockTaskPackagesLocked(userHandle); return packages.toArray(new String[packages.size()]); } getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); if (!isUserAffiliatedWithDeviceLocked(userHandle)) { throw new SecurityException("Admin " + who + " is neither the device owner or affiliated user's profile owner."); } private List<String> getLockTaskPackagesLocked(int userHandle) { final DevicePolicyData policy = getUserData(userHandle); return policy.mLockTaskPackages; final List<String> packages = getUserData(userHandle).mLockTaskPackages; return packages.toArray(new String[packages.size()]); } } /** * This function lets the caller know whether the given package is allowed to start the * lock task mode. * @param pkg The package to check */ @Override public boolean isLockTaskPermitted(String pkg) { // Get current user's devicepolicy int uid = mInjector.binderGetCallingUid(); int userHandle = UserHandle.getUserId(uid); DevicePolicyData policy = getUserData(userHandle); final int userHandle = mInjector.userHandleGetCallingUserId(); synchronized (this) { for (int i = 0; i < policy.mLockTaskPackages.size(); i++) { String lockTaskPackage = policy.mLockTaskPackages.get(i); // If the given package equals one of the packages stored our list, // we allow this package to start lock task mode. if (lockTaskPackage.equals(pkg)) { return true; } return getUserData(userHandle).mLockTaskPackages.contains(pkg); } } return false; } @Override public void notifyLockTaskModeChanged(boolean isEnabled, String pkg, int userHandle) { Loading Loading @@ -9848,6 +9844,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // but as a result of that other users might become affiliated or un-affiliated. maybePauseDeviceWideLoggingLocked(); maybeResumeDeviceWideLoggingLocked(); maybeClearLockTaskPackagesLocked(); } } Loading
services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +69 −0 Original line number Diff line number Diff line Loading @@ -3332,6 +3332,75 @@ public class DevicePolicyManagerTest extends DpmTestBase { MoreAsserts.assertEmpty(targetUsers); } public void testLockTaskPackagesAllowedForAffiliatedUsers() throws Exception { // Setup a device owner. mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; setupDeviceOwner(); // Lock task packages are updated when loading user data. verify(mContext.iactivityManager) .updateLockTaskPackages(eq(UserHandle.USER_SYSTEM), eq(new String[0])); // Set up a managed profile managed by different package (package name shouldn't matter) final int MANAGED_PROFILE_USER_ID = 15; final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(MANAGED_PROFILE_USER_ID, 20456); final ComponentName adminDifferentPackage = new ComponentName("another.package", "whatever.class"); addManagedProfile(adminDifferentPackage, MANAGED_PROFILE_ADMIN_UID, admin2); verify(mContext.iactivityManager) .updateLockTaskPackages(eq(MANAGED_PROFILE_USER_ID), eq(new String[0])); // The DO can still set lock task packages mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; final String[] doPackages = {"doPackage1", "doPackage2"}; dpm.setLockTaskPackages(admin1, doPackages); MoreAsserts.assertEquals(doPackages, dpm.getLockTaskPackages(admin1)); assertTrue(dpm.isLockTaskPermitted("doPackage1")); assertFalse(dpm.isLockTaskPermitted("anotherPackage")); verify(mContext.iactivityManager) .updateLockTaskPackages(eq(UserHandle.USER_SYSTEM), eq(doPackages)); // Managed profile is unaffiliated - shouldn't be able to setLockTaskPackages. mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID; final String[] poPackages = {"poPackage1", "poPackage2"}; try { dpm.setLockTaskPackages(adminDifferentPackage, poPackages); fail("Didn't throw expected security exception."); } catch (SecurityException expected) { } try { dpm.getLockTaskPackages(adminDifferentPackage); fail("Didn't throw expected security exception."); } catch (SecurityException expected) { } assertFalse(dpm.isLockTaskPermitted("doPackage1")); // Setting same affiliation ids final List<String> userAffiliationIds = Arrays.asList("some-affiliation-id"); mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; dpm.setAffiliationIds(admin1, userAffiliationIds); mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID; dpm.setAffiliationIds(adminDifferentPackage, userAffiliationIds); // Now the managed profile can set lock task packages. dpm.setLockTaskPackages(adminDifferentPackage, poPackages); MoreAsserts.assertEquals(poPackages, dpm.getLockTaskPackages(adminDifferentPackage)); assertTrue(dpm.isLockTaskPermitted("poPackage1")); assertFalse(dpm.isLockTaskPermitted("doPackage2")); verify(mContext.iactivityManager) .updateLockTaskPackages(eq(MANAGED_PROFILE_USER_ID), eq(poPackages)); // Unaffiliate the profile, lock task mode no longer available on the profile. dpm.setAffiliationIds(adminDifferentPackage, Collections.<String>emptyList()); assertFalse(dpm.isLockTaskPermitted("poPackage1")); // Lock task packages cleared when loading user data and when the user becomes unaffiliated. verify(mContext.iactivityManager, times(2)) .updateLockTaskPackages(eq(MANAGED_PROFILE_USER_ID), eq(new String[0])); mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; assertTrue(dpm.isLockTaskPermitted("doPackage1")); } public void testIsDeviceManaged() throws Exception { mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID; setupDeviceOwner(); Loading