DPM.isDeviceOwnerApp() and getDeviceOwner() now check calling user
- Previously on MNC, they would return the same result regardless who
the calling user is.
- Now they properly take DO user-id into account. Meaning, they'll
always return false and null respectively, if the calling user doesn't
run device owner.
- Note isDeviceOwnerApp() is a public API and getDeviceOwner() is
a system API. Meaning we're changing the behavior or non-private
APIs.
- Also cleaned up hidden APIs, and gave them explicit suffixes
to avoid confusion. Bundled code should prefer them for clarity.
Now we have:
* APIs that work cross-users: They all require MANAGE_USERS.
boolean isDeviceOwnerAppOnAnyUser(String packageName)
ComponentName getDeviceOwnerComponentOnAnyUser()
int getDeviceOwnerUserId()
boolean isDeviceOwnedByDeviceOwner()
String getDeviceOwnerNameOnAnyUser()
* APIs that work within user. No permissions are required.
boolean isDeviceOwnerAppOnCallingUser(String packageName)
ComponentName getDeviceOwnerComponentOnCallingUser()
Bug 24676413
Change-Id: I751a907c7aaf7b019335d67065d183236effaa80
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index cf09b84..5d1906c 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -866,10 +866,11 @@
mAppOps.checkPackage(callingUid, callerPackageName);
}
- // Check whether the caller is device owner
+ // Check whether the caller is device owner, in which case we do it silently.
DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
Context.DEVICE_POLICY_SERVICE);
- boolean isDeviceOwner = (dpm != null) && dpm.isDeviceOwnerApp(callerPackageName);
+ boolean isDeviceOwner = (dpm != null) && dpm.isDeviceOwnerAppOnCallingUser(
+ callerPackageName);
final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext,
statusReceiver, packageName, isDeviceOwner, userId);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index b0e43a5..fa0aa37 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -228,7 +228,8 @@
final boolean isInstallerRoot = (installerUid == Process.ROOT_UID);
final boolean forcePermissionPrompt =
(params.installFlags & PackageManager.INSTALL_FORCE_PERMISSION_PROMPT) != 0;
- mIsInstallerDeviceOwner = (dpm != null) && dpm.isDeviceOwnerApp(installerPackageName);
+ mIsInstallerDeviceOwner = (dpm != null) && dpm.isDeviceOwnerAppOnCallingUser(
+ installerPackageName);
if ((isPermissionGranted
|| isInstallerRoot
|| mIsInstallerDeviceOwner)
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 21a4206..4bc79cb 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -13065,7 +13065,8 @@
ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
try {
if (dpm != null) {
- final ComponentName deviceOwnerComponentName = dpm.getDeviceOwner();
+ final ComponentName deviceOwnerComponentName = dpm.getDeviceOwnerComponent(
+ /* callingUserOnly =*/ false);
final String deviceOwnerPackageName = deviceOwnerComponentName == null ? null
: deviceOwnerComponentName.getPackageName();
// Does the package contains the device owner?
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 558ea58..ff829ff 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -513,7 +513,7 @@
DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
Context.DEVICE_POLICY_SERVICE);
// restricted profile can be created if there is no DO set and the admin user has no PO
- return dpm.getDeviceOwner() == null && dpm.getProfileOwnerAsUser(userId) == null;
+ return !dpm.isDeviceManaged() && dpm.getProfileOwnerAsUser(userId) == null;
}
/*
@@ -1599,7 +1599,7 @@
DevicePolicyManager devicePolicyManager = (DevicePolicyManager)
mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
if (devicePolicyManager == null
- || devicePolicyManager.getDeviceOwner() == null) {
+ || !devicePolicyManager.isDeviceManaged()) {
flags |= UserInfo.FLAG_ADMIN;
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 8beee73..b3b647f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2045,9 +2045,12 @@
private void updateDeviceOwnerLocked() {
long ident = mInjector.binderClearCallingIdentity();
try {
- if (getDeviceOwner() != null) {
+ // TODO This is to prevent DO from getting "clear data"ed, but it should also check the
+ // user id and also protect all other DAs too.
+ final ComponentName deviceOwnerComponent = mOwners.getDeviceOwnerComponent();
+ if (deviceOwnerComponent != null) {
mInjector.getIActivityManager()
- .updateDeviceOwner(getDeviceOwner().getPackageName());
+ .updateDeviceOwner(deviceOwnerComponent.getPackageName());
}
} catch (RemoteException e) {
// Not gonna happen.
@@ -2248,6 +2251,7 @@
// Build and show a warning notification
int smallIconId;
String contentText;
+ // TODO Why does it use the DO name? The cert APIs are all for PO. b/25772443
final String ownerName = getDeviceOwnerName();
if (isManagedProfile(userHandle.getIdentifier())) {
contentText = mContext.getString(R.string.ssl_ca_cert_noti_by_administrator);
@@ -4600,22 +4604,46 @@
}
@Override
- public ComponentName getDeviceOwner() {
+ public ComponentName getDeviceOwnerComponent(boolean callingUserOnly) {
if (!mHasFeature) {
return null;
}
+ if (!callingUserOnly) {
+ enforceManageUsers();
+ }
synchronized (this) {
+ if (!mOwners.hasDeviceOwner()) {
+ return null;
+ }
+ if (callingUserOnly && mInjector.userHandleGetCallingUserId() !=
+ mOwners.getDeviceOwnerUserId()) {
+ return null;
+ }
return mOwners.getDeviceOwnerComponent();
}
}
@Override
+ public int getDeviceOwnerUserId() {
+ if (!mHasFeature) {
+ return UserHandle.USER_NULL;
+ }
+ enforceManageUsers();
+ synchronized (this) {
+ return mOwners.hasDeviceOwner() ? mOwners.getDeviceOwnerUserId() : UserHandle.USER_NULL;
+ }
+ }
+
+ /**
+ * Returns the "name" of the device owner. It'll work for non-DO users too, but requires
+ * MANAGE_USERS.
+ */
+ @Override
public String getDeviceOwnerName() {
if (!mHasFeature) {
return null;
}
- // TODO: Do we really need it? getDeviceOwner() doesn't require it.
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
+ enforceManageUsers();
synchronized (this) {
if (!mOwners.hasDeviceOwner()) {
return null;
@@ -4630,7 +4658,7 @@
// Returns the active device owner or null if there is no device owner.
@VisibleForTesting
ActiveAdmin getDeviceOwnerAdminLocked() {
- ComponentName component = getDeviceOwner();
+ ComponentName component = mOwners.getDeviceOwnerComponent();
if (component == null) {
return null;
}
@@ -4659,16 +4687,20 @@
} catch (NameNotFoundException e) {
throw new SecurityException(e);
}
- if (!mOwners.hasDeviceOwner() || !getDeviceOwner().getPackageName().equals(packageName)
- || (mOwners.getDeviceOwnerUserId() != UserHandle.getUserId(callingUid))) {
- throw new SecurityException("clearDeviceOwner can only be called by the device owner");
- }
synchronized (this) {
+ if (!mOwners.hasDeviceOwner()
+ || !mOwners.getDeviceOwnerComponent().getPackageName().equals(packageName)
+ || (mOwners.getDeviceOwnerUserId() != UserHandle.getUserId(callingUid))) {
+ throw new SecurityException(
+ "clearDeviceOwner can only be called by the device owner");
+ }
+
final ActiveAdmin admin = getDeviceOwnerAdminLocked();
if (admin != null) {
admin.disableCamera = false;
admin.userRestrictions = null;
}
+
clearUserPoliciesLocked(new UserHandle(UserHandle.USER_SYSTEM));
mOwners.clearDeviceOwner();
@@ -4857,7 +4889,7 @@
if (!mHasFeature) {
return null;
}
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
+ enforceManageUsers();
ComponentName profileOwner = getProfileOwner(userHandle);
if (profileOwner == null) {
return null;
@@ -4987,13 +5019,20 @@
}
}
+ private void enforceManageUsers() {
+ final int callingUid = mInjector.binderGetCallingUid();
+ if (!(UserHandle.isSameApp(callingUid, Process.SYSTEM_UID) || callingUid == 0)) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
+ }
+ }
+
private void enforceCrossUserPermission(int userHandle) {
if (userHandle < 0) {
throw new IllegalArgumentException("Invalid userId " + userHandle);
}
final int callingUid = mInjector.binderGetCallingUid();
if (userHandle == UserHandle.getUserId(callingUid)) return;
- if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
+ if (!(UserHandle.isSameApp(callingUid, Process.SYSTEM_UID) || callingUid == 0)) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, "Must be system or have"
+ " INTERACT_ACROSS_USERS_FULL permission");
@@ -6619,8 +6658,9 @@
updateReceivedTime);
synchronized (this) {
- final String deviceOwnerPackage = getDeviceOwner() == null ? null :
- getDeviceOwner().getPackageName();
+ final String deviceOwnerPackage =
+ mOwners.hasDeviceOwner() ? mOwners.getDeviceOwnerComponent().getPackageName()
+ : null;
if (deviceOwnerPackage == null) {
return;
}
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 0bd4896..79ba08d 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -27,6 +27,7 @@
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.os.Bundle;
+import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Pair;
@@ -35,6 +36,7 @@
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -56,9 +58,9 @@
*
m FrameworksServicesTests &&
adb install \
- -r out/target/product/hammerhead/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
+ -r out/target/product/hammerhead/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
adb shell am instrument -e class com.android.server.devicepolicy.DevicePolicyManagerTest \
- -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
(mmma frameworks/base/services/tests/servicestests/ for non-ninja build)
*/
@@ -458,6 +460,7 @@
*/
public void testSetDeviceOwner() throws Exception {
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
+ mContext.callerPermissions.add(permission.MANAGE_USERS);
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL);
@@ -467,12 +470,29 @@
// Make sure admin1 is installed on system user.
setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
+ // Check various get APIs.
+ checkGetDeviceOwnerInfoApi(dpm, /* hasDeviceOwner =*/ false);
+
// DO needs to be an DA.
dpm.setActiveAdmin(admin1, /* replace =*/ false);
// Fire!
assertTrue(dpm.setDeviceOwner(admin1, "owner-name"));
+ // getDeviceOwnerComponent should return the admin1 component.
+ assertEquals(admin1, dpm.getDeviceOwnerComponentOnCallingUser());
+ assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
+
+ // Check various get APIs.
+ checkGetDeviceOwnerInfoApi(dpm, /* hasDeviceOwner =*/ true);
+
+ // getDeviceOwnerComponent should *NOT* return the admin1 component for other users.
+ mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+ assertEquals(null, dpm.getDeviceOwnerComponentOnCallingUser());
+ assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
+
+ mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+
// Verify internal calls.
verify(mContext.iactivityManager, times(1)).updateDeviceOwner(
eq(admin1.getPackageName()));
@@ -485,7 +505,7 @@
MockUtils.checkIntentAction(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED),
MockUtils.checkUserHandle(UserHandle.USER_SYSTEM));
- assertEquals(admin1.getPackageName(), dpm.getDeviceOwner());
+ assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
// Try to set a profile owner on the same user, which should fail.
setUpPackageManagerForAdmin(admin2, DpmMockContext.CALLER_SYSTEM_USER_UID);
@@ -502,11 +522,163 @@
// DPMS.getApplicationLabel() because Context.createPackageContextAsUser() is not mockable.
}
+ private void checkGetDeviceOwnerInfoApi(DevicePolicyManager dpm, boolean hasDeviceOwner) {
+ final int origCallingUser = mContext.binder.callingUid;
+ final List origPermissions = new ArrayList(mContext.callerPermissions);
+ mContext.callerPermissions.clear();
+
+ mContext.callerPermissions.add(permission.MANAGE_USERS);
+
+ mContext.binder.callingUid = Process.SYSTEM_UID;
+
+ // TODO Test getDeviceOwnerName() too. To do so, we need to change
+ // DPMS.getApplicationLabel() because Context.createPackageContextAsUser() is not mockable.
+ if (hasDeviceOwner) {
+ assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
+ assertTrue(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
+ assertEquals(admin1, dpm.getDeviceOwnerComponentOnCallingUser());
+
+ assertTrue(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
+ assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
+ assertEquals(UserHandle.USER_SYSTEM, dpm.getDeviceOwnerUserId());
+ } else {
+ assertFalse(dpm.isDeviceOwnerApp(admin1.getPackageName()));
+ assertFalse(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
+ assertEquals(null, dpm.getDeviceOwnerComponentOnCallingUser());
+
+ assertFalse(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
+ assertEquals(null, dpm.getDeviceOwnerComponentOnAnyUser());
+ assertEquals(UserHandle.USER_NULL, dpm.getDeviceOwnerUserId());
+ }
+
+ mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ if (hasDeviceOwner) {
+ assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
+ assertTrue(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
+ assertEquals(admin1, dpm.getDeviceOwnerComponentOnCallingUser());
+
+ assertTrue(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
+ assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
+ assertEquals(UserHandle.USER_SYSTEM, dpm.getDeviceOwnerUserId());
+ } else {
+ assertFalse(dpm.isDeviceOwnerApp(admin1.getPackageName()));
+ assertFalse(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
+ assertEquals(null, dpm.getDeviceOwnerComponentOnCallingUser());
+
+ assertFalse(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
+ assertEquals(null, dpm.getDeviceOwnerComponentOnAnyUser());
+ assertEquals(UserHandle.USER_NULL, dpm.getDeviceOwnerUserId());
+ }
+
+ mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+ // Still with MANAGE_USERS.
+ assertFalse(dpm.isDeviceOwnerApp(admin1.getPackageName()));
+ assertFalse(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
+ assertEquals(null, dpm.getDeviceOwnerComponentOnCallingUser());
+
+ if (hasDeviceOwner) {
+ assertTrue(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
+ assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
+ assertEquals(UserHandle.USER_SYSTEM, dpm.getDeviceOwnerUserId());
+ } else {
+ assertFalse(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
+ assertEquals(null, dpm.getDeviceOwnerComponentOnAnyUser());
+ assertEquals(UserHandle.USER_NULL, dpm.getDeviceOwnerUserId());
+ }
+
+ mContext.binder.callingUid = Process.SYSTEM_UID;
+ mContext.callerPermissions.remove(permission.MANAGE_USERS);
+ // System can still call "OnAnyUser" without MANAGE_USERS.
+ if (hasDeviceOwner) {
+ assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
+ assertTrue(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
+ assertEquals(admin1, dpm.getDeviceOwnerComponentOnCallingUser());
+
+ assertTrue(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
+ assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
+ assertEquals(UserHandle.USER_SYSTEM, dpm.getDeviceOwnerUserId());
+ } else {
+ assertFalse(dpm.isDeviceOwnerApp(admin1.getPackageName()));
+ assertFalse(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
+ assertEquals(null, dpm.getDeviceOwnerComponentOnCallingUser());
+
+ assertFalse(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
+ assertEquals(null, dpm.getDeviceOwnerComponentOnAnyUser());
+ assertEquals(UserHandle.USER_NULL, dpm.getDeviceOwnerUserId());
+ }
+
+ mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ // Still no MANAGE_USERS.
+ if (hasDeviceOwner) {
+ assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
+ assertTrue(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
+ assertEquals(admin1, dpm.getDeviceOwnerComponentOnCallingUser());
+ } else {
+ assertFalse(dpm.isDeviceOwnerApp(admin1.getPackageName()));
+ assertFalse(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
+ assertEquals(null, dpm.getDeviceOwnerComponentOnCallingUser());
+ }
+
+ try {
+ dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName());
+ fail();
+ } catch (SecurityException expected) {
+ }
+ try {
+ dpm.getDeviceOwnerComponentOnAnyUser();
+ fail();
+ } catch (SecurityException expected) {
+ }
+ try {
+ dpm.getDeviceOwnerUserId();
+ fail();
+ } catch (SecurityException expected) {
+ }
+ try {
+ dpm.getDeviceOwnerNameOnAnyUser();
+ fail();
+ } catch (SecurityException expected) {
+ }
+
+ mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+ // Still no MANAGE_USERS.
+ assertFalse(dpm.isDeviceOwnerApp(admin1.getPackageName()));
+ assertFalse(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
+ assertEquals(null, dpm.getDeviceOwnerComponentOnCallingUser());
+
+ try {
+ dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName());
+ fail();
+ } catch (SecurityException expected) {
+ }
+ try {
+ dpm.getDeviceOwnerComponentOnAnyUser();
+ fail();
+ } catch (SecurityException expected) {
+ }
+ try {
+ dpm.getDeviceOwnerUserId();
+ fail();
+ } catch (SecurityException expected) {
+ }
+ try {
+ dpm.getDeviceOwnerNameOnAnyUser();
+ fail();
+ } catch (SecurityException expected) {
+ }
+
+ // Restore.
+ mContext.binder.callingUid = origCallingUser;
+ mContext.callerPermissions.addAll(origPermissions);
+ }
+
+
/**
* Test for: {@link DevicePolicyManager#setDeviceOwner} Package doesn't exist.
*/
public void testSetDeviceOwner_noSuchPackage() {
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
+ mContext.callerPermissions.add(permission.MANAGE_USERS);
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL);
@@ -528,6 +700,7 @@
public void testClearDeviceOwner() throws Exception {
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
+ mContext.callerPermissions.add(permission.MANAGE_USERS);
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL);
@@ -547,7 +720,7 @@
verify(mContext.iactivityManager, times(1)).updateDeviceOwner(
eq(admin1.getPackageName()));
- assertEquals(admin1.getPackageName(), dpm.getDeviceOwner());
+ assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
// Set up other mocks.
when(mContext.userManager.getUserRestrictions()).thenReturn(new Bundle());
@@ -559,13 +732,14 @@
dpm.clearDeviceOwnerApp(admin1.getPackageName());
// Now DO shouldn't be set.
- assertNull(dpm.getDeviceOwner());
+ assertNull(dpm.getDeviceOwnerComponentOnAnyUser());
// TODO Check other calls.
}
public void testClearDeviceOwner_fromDifferentUser() throws Exception {
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
+ mContext.callerPermissions.add(permission.MANAGE_USERS);
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL);
@@ -585,7 +759,7 @@
verify(mContext.iactivityManager, times(1)).updateDeviceOwner(
eq(admin1.getPackageName()));
- assertEquals(admin1.getPackageName(), dpm.getDeviceOwner());
+ assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
// Now call clear from the secondary user, which should throw.
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
@@ -601,8 +775,8 @@
assertEquals("clearDeviceOwner can only be called by the device owner", e.getMessage());
}
- // Now DO shouldn't be set.
- assertNotNull(dpm.getDeviceOwner());
+ // DO shouldn't be removed.
+ assertTrue(dpm.isDeviceManaged());
}
public void testSetProfileOwner() throws Exception {
@@ -639,6 +813,7 @@
mMockContext.addUser(ANOTHER_USER_ID, 0); // Add one more user.
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
+ mContext.callerPermissions.add(permission.MANAGE_USERS);
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL);
@@ -667,8 +842,7 @@
mContext.setUserRunning(DpmMockContext.CALLER_USER_HANDLE, true);
assertTrue(dpm.setDeviceOwner(admin2, "owner-name", DpmMockContext.CALLER_USER_HANDLE));
- // Make sure it's set.
- assertEquals(admin2, dpm.getDeviceOwnerComponent());
+ assertEquals(admin2, dpms.getDeviceOwnerComponent(/* callingUserOnly =*/ false));
// Then check getDeviceOwnerAdminLocked().
assertEquals(admin2, dpms.getDeviceOwnerAdminLocked().info.getComponent());
@@ -692,7 +866,7 @@
dpms.mOwners.writeDeviceOwner();
// Make sure the DO component name doesn't have a class name.
- assertEquals("", dpms.getDeviceOwner().getClassName());
+ assertEquals("", dpms.getDeviceOwnerComponent(/* callingUserOnly =*/ false).getClassName());
// Then create a new DPMS to have it load the settings from files.
when(mContext.userManager.getUserRestrictions(any(UserHandle.class)))
@@ -702,7 +876,7 @@
// Now the DO component name is a full name.
// *BUT* because both admin1 and admin2 belong to the same package, we think admin1 is the
// DO.
- assertEquals(admin1, dpms.getDeviceOwner());
+ assertEquals(admin1, dpms.getDeviceOwnerComponent(/* callingUserOnly =*/ false));
}
public void testSetGetApplicationRestriction() {
@@ -740,6 +914,7 @@
public void testSetUserRestriction_asDo() throws Exception {
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
+ mContext.callerPermissions.add(permission.MANAGE_USERS);
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL);