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
This commit is contained in:
Makoto Onuki
2015-11-19 14:29:12 -08:00
parent abef6d6f2b
commit c8a5a555f1
11 changed files with 361 additions and 80 deletions

View File

@ -89,6 +89,10 @@ public class DevicePolicyManager {
private final Context mContext;
private final IDevicePolicyManager mService;
// TODO Use it everywhere.
private static final String REMOTE_EXCEPTION_MESSAGE =
"Failed to talk with device policy manager service";
private DevicePolicyManager(Context context) {
this(context, IDevicePolicyManager.Stub.asInterface(
ServiceManager.getService(Context.DEVICE_POLICY_SERVICE)));
@ -686,7 +690,7 @@ public class DevicePolicyManager {
* extra field. This will invoke a UI to bring the user through adding the profile owner admin
* to remotely control restrictions on the user.
*
* <p>The intent must be invoked via {@link Activity#startActivityForResult()} to receive the
* <p>The intent must be invoked via {@link Activity#startActivityForResult} to receive the
* result of whether or not the user approved the action. If approved, the result will
* be {@link Activity#RESULT_OK} and the component will be set as an active admin as well
* as a profile owner.
@ -2765,37 +2769,94 @@ public class DevicePolicyManager {
* the setup process.
* @param packageName the package name of the app, to compare with the registered device owner
* app, if any.
* @return whether or not the package is registered as the device owner app. Note this method
* does *not* check weather the device owner is actually running on the current user.
* @return whether or not the package is registered as the device owner app.
*/
public boolean isDeviceOwnerApp(String packageName) {
return isDeviceOwnerAppOnCallingUser(packageName);
}
/**
* @return true if a package is registered as device owner, only when it's running on the
* calling user.
*
* <p>Same as {@link #isDeviceOwnerApp}, but bundled code should use it for clarity.
* @hide
*/
public boolean isDeviceOwnerAppOnCallingUser(String packageName) {
return isDeviceOwnerAppOnAnyUserInner(packageName, /* callingUserOnly =*/ true);
}
/**
* @return true if a package is registered as device owner, even if it's running on a different
* user.
*
* <p>Requires the MANAGE_USERS permission.
*
* @hide
*/
public boolean isDeviceOwnerAppOnAnyUser(String packageName) {
return isDeviceOwnerAppOnAnyUserInner(packageName, /* callingUserOnly =*/ false);
}
/**
* @return device owner component name, only when it's running on the calling user.
*
* @hide
*/
public ComponentName getDeviceOwnerComponentOnCallingUser() {
return getDeviceOwnerComponentInner(/* callingUserOnly =*/ true);
}
/**
* @return device owner component name, even if it's running on a different user.
*
* <p>Requires the MANAGE_USERS permission.
*
* @hide
*/
public ComponentName getDeviceOwnerComponentOnAnyUser() {
return getDeviceOwnerComponentInner(/* callingUserOnly =*/ false);
}
private boolean isDeviceOwnerAppOnAnyUserInner(String packageName, boolean callingUserOnly) {
if (packageName == null) {
return false;
}
final ComponentName deviceOwner = getDeviceOwnerComponent();
final ComponentName deviceOwner = getDeviceOwnerComponentInner(callingUserOnly);
if (deviceOwner == null) {
return false;
}
return packageName.equals(deviceOwner.getPackageName());
}
/**
* @hide
* Redirect to isDeviceOwnerApp.
*/
public boolean isDeviceOwner(String packageName) {
return isDeviceOwnerApp(packageName);
private ComponentName getDeviceOwnerComponentInner(boolean callingUserOnly) {
if (mService != null) {
try {
return mService.getDeviceOwnerComponent(callingUserOnly);
} catch (RemoteException re) {
Log.w(TAG, REMOTE_EXCEPTION_MESSAGE);
}
}
return null;
}
/**
* Check whether a given component is registered as a device owner.
* Note this method does *not* check weather the device owner is actually running on the current
* user.
* @return ID of the user who runs device owner, or {@link UserHandle#USER_NULL} if there's
* no device owner.
*
* <p>Requires the MANAGE_USERS permission.
*
* @hide
*/
public boolean isDeviceOwner(ComponentName who) {
return (who != null) && who.equals(getDeviceOwner());
public int getDeviceOwnerUserId() {
if (mService != null) {
try {
return mService.getDeviceOwnerUserId();
} catch (RemoteException re) {
Log.w(TAG, REMOTE_EXCEPTION_MESSAGE);
}
}
return UserHandle.USER_NULL;
}
/**
@ -2818,46 +2879,43 @@ public class DevicePolicyManager {
}
/**
* Returns the device owner package name. Note this method will still return the device owner
* package name even if it's running on a different user.
* Returns the device owner package name, only if it's running on the calling user.
*
* <p>Bundled components should use {@code getDeviceOwnerComponentOnCallingUser()} for clarity.
*
* @hide
*/
@SystemApi
public String getDeviceOwner() {
final ComponentName componentName = getDeviceOwnerComponent();
return componentName == null ? null : componentName.getPackageName();
final ComponentName name = getDeviceOwnerComponentOnCallingUser();
return name != null ? name.getPackageName() : null;
}
/**
* Returns the device owner name. Note this method will still return the device owner
* name even if it's running on a different user.
* @return true if the device is managed by any device owner.
*
* <p>Requires the MANAGE_USERS permission.
*
* @hide
*/
public String getDeviceOwnerName() {
public boolean isDeviceManaged() {
return getDeviceOwnerComponentOnAnyUser() != null;
}
/**
* Returns the device owner name. Note this method *will* return the device owner
* name when it's running on a different user.
*
* <p>Requires the MANAGE_USERS permission.
*
* @hide
*/
public String getDeviceOwnerNameOnAnyUser() {
if (mService != null) {
try {
return mService.getDeviceOwnerName();
} catch (RemoteException re) {
Log.w(TAG, "Failed to get device owner");
}
}
return null;
}
/**
* Returns the device owner component name. Note this method will still return the device owner
* component name even if it's running on a different user.
*
* @hide
*/
public ComponentName getDeviceOwnerComponent() {
if (mService != null) {
try {
return mService.getDeviceOwner();
} catch (RemoteException re) {
Log.w(TAG, "Failed to get device owner");
Log.w(TAG, REMOTE_EXCEPTION_MESSAGE);
}
}
return null;
@ -3130,7 +3188,7 @@ public class DevicePolicyManager {
/**
* @hide
* @param user The user for whom to fetch the profile owner name, if any.
* @param userId The user for whom to fetch the profile owner name, if any.
* @return the human readable name of the organisation associated with this profile owner or
* null if one is not set.
* @throws IllegalArgumentException if the userId is invalid.

View File

@ -114,9 +114,10 @@ interface IDevicePolicyManager {
void reportSuccessfulPasswordAttempt(int userHandle);
boolean setDeviceOwner(in ComponentName who, String ownerName, int userId);
ComponentName getDeviceOwner();
ComponentName getDeviceOwnerComponent(boolean callingUserOnly);
String getDeviceOwnerName();
void clearDeviceOwner(String packageName);
int getDeviceOwnerUserId();
boolean setProfileOwner(in ComponentName who, String ownerName, int userHandle);
ComponentName getProfileOwner(int userHandle);

View File

@ -111,7 +111,9 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene
private void handleRefreshState() {
mIsIconVisible = mSecurityController.isVpnEnabled();
if (mSecurityController.hasDeviceOwner()) {
// If the device has device owner, show "Device may be monitored", but --
// TODO See b/25779452 -- device owner doesn't actually have monitoring power.
if (mSecurityController.isDeviceManaged()) {
mFooterTextId = R.string.device_owned_footer;
mIsVisible = true;
} else {
@ -156,6 +158,8 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene
private String getMessage(String deviceOwner, String profileOwner, String primaryVpn,
String profileVpn, boolean primaryUserIsManaged) {
// Show a special warning when the device has device owner, but --
// TODO See b/25779452 -- device owner doesn't actually have monitoring power.
if (deviceOwner != null) {
if (primaryVpn != null) {
return mContext.getString(R.string.monitoring_description_vpn_app_device_owned,

View File

@ -16,8 +16,8 @@
package com.android.systemui.statusbar.policy;
public interface SecurityController {
boolean hasDeviceOwner();
/** Whether the device has device owner, even if not on this user. */
boolean isDeviceManaged();
boolean hasProfileOwner();
String getDeviceOwnerName();
String getProfileOwnerName();

View File

@ -102,13 +102,13 @@ public class SecurityControllerImpl implements SecurityController {
}
@Override
public boolean hasDeviceOwner() {
return !TextUtils.isEmpty(mDevicePolicyManager.getDeviceOwner());
public boolean isDeviceManaged() {
return mDevicePolicyManager.isDeviceManaged();
}
@Override
public String getDeviceOwnerName() {
return mDevicePolicyManager.getDeviceOwnerName();
return mDevicePolicyManager.getDeviceOwnerNameOnAnyUser();
}
@Override

View File

@ -866,10 +866,11 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
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);

View File

@ -228,7 +228,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
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)

View File

@ -13065,7 +13065,8 @@ public class PackageManagerService extends IPackageManager.Stub {
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?

View File

@ -513,7 +513,7 @@ public class UserManagerService extends IUserManager.Stub {
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 @@ public class UserManagerService extends IUserManager.Stub {
DevicePolicyManager devicePolicyManager = (DevicePolicyManager)
mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
if (devicePolicyManager == null
|| devicePolicyManager.getDeviceOwner() == null) {
|| !devicePolicyManager.isDeviceManaged()) {
flags |= UserInfo.FLAG_ADMIN;
}
}

View File

@ -2045,9 +2045,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
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 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// 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 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
@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 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// 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 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} 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 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
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 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
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 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
updateReceivedTime);
synchronized (this) {
final String deviceOwnerPackage = getDeviceOwner() == null ? null :
getDeviceOwner().getPackageName();
final String deviceOwnerPackage =
mOwners.hasDeviceOwner() ? mOwners.getDeviceOwnerComponent().getPackageName()
: null;
if (deviceOwnerPackage == null) {
return;
}

View File

@ -27,6 +27,7 @@ import android.content.BroadcastReceiver;
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.ArgumentCaptor;
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 @@ import static org.mockito.Mockito.when;
*
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 class DevicePolicyManagerTest extends DpmTestBase {
*/
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 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// 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 @@ public class DevicePolicyManagerTest extends DpmTestBase {
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 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// 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 class DevicePolicyManagerTest extends DpmTestBase {
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 @@ public class DevicePolicyManagerTest extends DpmTestBase {
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 @@ public class DevicePolicyManagerTest extends DpmTestBase {
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 @@ public class DevicePolicyManagerTest extends DpmTestBase {
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 @@ public class DevicePolicyManagerTest extends DpmTestBase {
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 @@ public class DevicePolicyManagerTest extends DpmTestBase {
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 @@ public class DevicePolicyManagerTest extends DpmTestBase {
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 @@ public class DevicePolicyManagerTest extends DpmTestBase {
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 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// 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 class DevicePolicyManagerTest extends DpmTestBase {
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);