summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2016-11-24 18:02:20 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2016-11-24 18:02:23 +0000
commit8d4527db199b67de3a142a37adaa887bd026c22c (patch)
treec0a419a3388e51ad44e5faec30c5d7d2c5b24240
parent5ce42bba5080fec4987a4a9ae2b93978d2266c35 (diff)
parentfc291bcbe007692ab7a6de0651769b1f2e09de49 (diff)
Merge "Add getBindDeviceAdminTargetUsers API"
-rw-r--r--api/current.txt1
-rw-r--r--api/system-current.txt1
-rw-r--r--api/test-current.txt1
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java36
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl1
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java130
6 files changed, 120 insertions, 50 deletions
diff --git a/api/current.txt b/api/current.txt
index 33564a28ddf3..e42913c57d98 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6007,6 +6007,7 @@ package android.app.admin {
method public android.os.Bundle getApplicationRestrictions(android.content.ComponentName, java.lang.String);
method public java.lang.String getApplicationRestrictionsManagingPackage(android.content.ComponentName);
method public boolean getAutoTimeRequired();
+ method public java.util.List<android.os.UserHandle> getBindDeviceAdminTargetUsers(android.content.ComponentName);
method public boolean getBluetoothContactSharingDisabled(android.content.ComponentName);
method public boolean getCameraDisabled(android.content.ComponentName);
method public java.lang.String getCertInstallerPackage(android.content.ComponentName) throws java.lang.SecurityException;
diff --git a/api/system-current.txt b/api/system-current.txt
index 150d92515845..873f0215d16c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -6179,6 +6179,7 @@ package android.app.admin {
method public android.os.Bundle getApplicationRestrictions(android.content.ComponentName, java.lang.String);
method public java.lang.String getApplicationRestrictionsManagingPackage(android.content.ComponentName);
method public boolean getAutoTimeRequired();
+ method public java.util.List<android.os.UserHandle> getBindDeviceAdminTargetUsers(android.content.ComponentName);
method public boolean getBluetoothContactSharingDisabled(android.content.ComponentName);
method public boolean getCameraDisabled(android.content.ComponentName);
method public java.lang.String getCertInstallerPackage(android.content.ComponentName) throws java.lang.SecurityException;
diff --git a/api/test-current.txt b/api/test-current.txt
index 0730cc4a5216..4f2bea5956a0 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -6023,6 +6023,7 @@ package android.app.admin {
method public android.os.Bundle getApplicationRestrictions(android.content.ComponentName, java.lang.String);
method public java.lang.String getApplicationRestrictionsManagingPackage(android.content.ComponentName);
method public boolean getAutoTimeRequired();
+ method public java.util.List<android.os.UserHandle> getBindDeviceAdminTargetUsers(android.content.ComponentName);
method public boolean getBluetoothContactSharingDisabled(android.content.ComponentName);
method public boolean getCameraDisabled(android.content.ComponentName);
method public java.lang.String getCertInstallerPackage(android.content.ComponentName) throws java.lang.SecurityException;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index ef1e55a5880b..2fa231863810 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -6713,11 +6713,14 @@ public class DevicePolicyManager {
}
/**
- * Called by device owner/ profile owner in managed profile to bind the service with each other.
+ * Called by a device owner to bind to a service from a profile owner of a managed profile or
+ * vice versa. See {@link #getBindDeviceAdminTargetUsers} for a definition of which
+ * device/profile owners are allowed to bind to services of another profile/device owner.
+ * <p>
* The service must be unexported. Note that the {@link Context} used to obtain this
* {@link DevicePolicyManager} instance via {@link Context#getSystemService(Class)} will be used
* to bind to the {@link android.app.Service}.
- * STOPSHIP (b/31952368): Update the javadoc after we policy to control which packages can talk.
+ *
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param serviceIntent Identifies the service to connect to. The Intent must specify either an
* explicit component name or a package name to match an
@@ -6726,11 +6729,15 @@ public class DevicePolicyManager {
* valid {@link ServiceConnection} object; it must not be {@code null}.
* @param flags Operation options for the binding operation. See
* {@link Context#bindService(Intent, ServiceConnection, int)}.
- * @param targetUser Which user to bind to.
+ * @param targetUser Which user to bind to. Must be one of the users returned by
+ * {@link #getBindDeviceAdminTargetUsers}, otherwise a {@link SecurityException} will
+ * be thrown.
* @return If you have successfully bound to the service, {@code true} is returned;
* {@code false} is returned if the connection is not made and you will not
* receive the service object.
+ *
* @see Context#bindService(Intent, ServiceConnection, int)
+ * @see #getBindDeviceAdminTargetUsers(ComponentName)
*/
public boolean bindDeviceAdminServiceAsUser(
@NonNull ComponentName admin, Intent serviceIntent, @NonNull ServiceConnection conn,
@@ -6749,6 +6756,29 @@ public class DevicePolicyManager {
}
/**
+ * Returns the list of target users that the calling device or profile owner can use when
+ * calling {@link #bindDeviceAdminServiceAsUser}.
+ * <p>
+ * A device owner can bind to a service from a profile owner of a managed profile and
+ * vice versa, provided that:
+ * <ul>
+ * <li>Both belong to the same package name.
+ * <li>The managed profile is a profile of the user where the device owner is set.
+ * See {@link UserManager#getUserProfiles()}
+ * <li>Both users are affiliated.
+ * STOPSHIP(b/32326223) Add reference to setAffiliationIds here once public.
+ * </ul>
+ */
+ public @NonNull List<UserHandle> getBindDeviceAdminTargetUsers(@NonNull ComponentName admin) {
+ throwIfParentInstance("getBindDeviceAdminTargetUsers");
+ try {
+ return mService.getBindDeviceAdminTargetUsers(admin);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Called by the system to get the time at which the device owner last retrieved security
* logging entries.
*
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index d14e0d0dfdf0..b7e0e9266e0e 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -325,6 +325,7 @@ interface IDevicePolicyManager {
boolean bindDeviceAdminServiceAsUser(in ComponentName admin,
IApplicationThread caller, IBinder token, in Intent service,
IServiceConnection connection, int flags, int targetUserId);
+ List<UserHandle> getBindDeviceAdminTargetUsers(in ComponentName admin);
long getLastSecurityLogRetrievalTime();
long getLastBugReportRequestTime();
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 29c90193d8a0..f7bb190990b0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -6634,7 +6634,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
private boolean isManagedProfile(int userHandle) {
- return getUserInfo(userHandle).isManagedProfile();
+ final UserInfo user = getUserInfo(userHandle);
+ return user != null && user.isManagedProfile();
}
private void enableIfNecessary(String packageName, int userId) {
@@ -8903,9 +8904,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
}
- final int callingUserId = mInjector.userHandleGetCallingUserId();
- final UserInfo user = getUserInfo(callingUserId);
- return user != null && user.isManagedProfile();
+ return isManagedProfile(mInjector.userHandleGetCallingUserId());
}
@Override
@@ -9537,65 +9536,97 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Preconditions.checkNotNull(caller);
Preconditions.checkNotNull(serviceIntent);
Preconditions.checkNotNull(connection);
- final int callingUserId = mInjector.userHandleGetCallingUserId();
- Preconditions.checkArgument(callingUserId != targetUserId,
+ Preconditions.checkArgument(mInjector.userHandleGetCallingUserId() != targetUserId,
"target user id must be different from the calling user id");
+ if (!getBindDeviceAdminTargetUsers(admin).contains(UserHandle.of(targetUserId))) {
+ throw new SecurityException("Not allowed to bind to target user id");
+ }
+
+ final String targetPackage;
synchronized (this) {
- final ActiveAdmin callingAdmin = getActiveAdminForCallerLocked(admin,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- // Ensure the target user is valid.
- if (isDeviceOwner(callingAdmin)) {
- enforceManagedProfile(targetUserId, "Target user must be a managed profile");
- } else {
- // Further lock down to profile owner in managed profile.
- enforceManagedProfile(callingUserId,
- "Only support profile owner in managed profile.");
- if (mOwners.getDeviceOwnerUserId() != targetUserId) {
- throw new SecurityException("Target user must be a device owner.");
- }
- }
+ targetPackage = getOwnerPackageNameForUserLocked(targetUserId);
}
+
final long callingIdentity = mInjector.binderClearCallingIdentity();
try {
- if (!mUserManager.isSameProfileGroup(callingUserId, targetUserId)) {
- throw new SecurityException(
- "Can only bind service across users under the same profile group");
- }
- final String targetPackage;
- synchronized (this) {
- targetPackage = getOwnerPackageNameForUserLocked(targetUserId);
- }
- // STOPSHIP(b/31952368): Add policy to control which packages can talk.
- if (TextUtils.isEmpty(targetPackage) || !targetPackage.equals(admin.getPackageName())) {
- throw new SecurityException("Device owner and profile owner must be the same " +
- "package in order to communicate.");
- }
// Validate and sanitize the incoming service intent.
final Intent sanitizedIntent =
- createCrossUserServiceIntent(serviceIntent, targetPackage);
+ createCrossUserServiceIntent(serviceIntent, targetPackage, targetUserId);
if (sanitizedIntent == null) {
// Fail, cannot lookup the target service.
throw new SecurityException("Invalid intent or failed to look up the service");
}
+
// Ask ActivityManager to bind it. Notice that we are binding the service with the
// caller app instead of DevicePolicyManagerService.
- try {
- return mInjector.getIActivityManager().bindService(
- caller, activtiyToken, serviceIntent,
- serviceIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
- connection, flags, mContext.getOpPackageName(),
- targetUserId) != 0;
- } catch (RemoteException ex) {
- // Same process, should not happen.
- }
+ return mInjector.getIActivityManager().bindService(
+ caller, activtiyToken, serviceIntent,
+ serviceIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
+ connection, flags, mContext.getOpPackageName(),
+ targetUserId) != 0;
+ } catch (RemoteException ex) {
+ // Same process, should not happen.
} finally {
mInjector.binderRestoreCallingIdentity(callingIdentity);
}
- // Fail to bind.
+
+ // Failed to bind.
return false;
}
+ @Override
+ public @NonNull List<UserHandle> getBindDeviceAdminTargetUsers(@NonNull ComponentName admin) {
+ if (!mHasFeature) {
+ return Collections.emptyList();
+ }
+ Preconditions.checkNotNull(admin);
+ ArrayList<UserHandle> targetUsers = new ArrayList<>();
+
+ synchronized (this) {
+ ActiveAdmin callingOwner = getActiveAdminForCallerLocked(
+ admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+ final int callingUserId = mInjector.userHandleGetCallingUserId();
+ final boolean isCallerDeviceOwner = isDeviceOwner(callingOwner);
+ final boolean isCallerManagedProfile = isManagedProfile(callingUserId);
+ if (!isCallerDeviceOwner && !isCallerManagedProfile
+ /* STOPSHIP(b/32326223) Reinstate when setAffiliationIds is public
+ || !isAffiliatedUser(callingUserId) */) {
+ return targetUsers;
+ }
+
+ final long callingIdentity = mInjector.binderClearCallingIdentity();
+ try {
+ String callingOwnerPackage = callingOwner.info.getComponent().getPackageName();
+ for (int userId : mUserManager.getProfileIds(
+ callingUserId, /* enabledOnly= */ false)) {
+ if (userId == callingUserId) {
+ continue;
+ }
+
+ // We only allow the device owner and a managed profile owner to bind to each
+ // other.
+ if ((isCallerManagedProfile && userId == mOwners.getDeviceOwnerUserId())
+ || (isCallerDeviceOwner && isManagedProfile(userId))) {
+ String targetOwnerPackage = getOwnerPackageNameForUserLocked(userId);
+
+ // Both must be the same package and be affiliated in order to bind.
+ if (callingOwnerPackage.equals(targetOwnerPackage)
+ /* STOPSHIP(b/32326223) Reinstate when setAffiliationIds is public
+ && isAffiliatedUser(userId)*/) {
+ targetUsers.add(UserHandle.of(userId));
+ }
+ }
+ }
+ } finally {
+ mInjector.binderRestoreCallingIdentity(callingIdentity);
+ }
+ }
+
+ return targetUsers;
+ }
+
/**
* Return true if a given user has any accounts that'll prevent installing a device or profile
* owner {@code owner}.
@@ -9776,7 +9807,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* Return the package name of owner in a given user.
*/
private String getOwnerPackageNameForUserLocked(int userId) {
- return getDeviceOwnerUserId() == userId
+ return mOwners.getDeviceOwnerUserId() == userId
? mOwners.getDeviceOwnerPackageName()
: mOwners.getProfileOwnerPackage(userId);
}
@@ -9787,14 +9818,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* @return Intent that have component explicitly set. {@code null} if the incoming intent
* or target service is invalid.
*/
- private Intent createCrossUserServiceIntent (
- @NonNull Intent rawIntent, @NonNull String expectedPackageName) {
+ private Intent createCrossUserServiceIntent(
+ @NonNull Intent rawIntent, @NonNull String expectedPackageName,
+ @UserIdInt int targetUserId) throws RemoteException {
if (rawIntent.getComponent() == null && rawIntent.getPackage() == null) {
Log.e(LOG_TAG, "Service intent must be explicit (with a package name or component): "
+ rawIntent);
return null;
}
- ResolveInfo info = mInjector.getPackageManager().resolveService(rawIntent, 0);
+ ResolveInfo info = mIPackageManager.resolveService(
+ rawIntent,
+ rawIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
+ 0, // flags
+ targetUserId);
if (info == null || info.serviceInfo == null) {
Log.e(LOG_TAG, "Fail to look up the service: " + rawIntent);
return null;