Merge "Allow DO to disable camera device-wise."

This commit is contained in:
Makoto Onuki
2015-11-02 22:00:09 +00:00
committed by Android (Google) Code Review
5 changed files with 59 additions and 45 deletions

View File

@@ -653,7 +653,7 @@ public class AppOpsManager {
null, //WRITE_SETTINGS
UserManager.DISALLOW_CREATE_WINDOWS, //SYSTEM_ALERT_WINDOW
null, //ACCESS_NOTIFICATIONS
null, //CAMERA
UserManager.DISALLOW_CAMERA, //CAMERA
UserManager.DISALLOW_RECORD_AUDIO, //RECORD_AUDIO
null, //PLAY_AUDIO
null, //READ_CLIPBOARD

View File

@@ -2271,6 +2271,8 @@ public class DevicePolicyManager {
* on the device, for this user. After setting this, no applications running as this user
* will be able to access any cameras on the device.
*
* <p>If the caller is device owner, then the restriction will be applied to all users.
*
* <p>The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA} to be able to call
* this method; if it has not, a security exception will be thrown.

View File

@@ -486,6 +486,16 @@ public class UserManager {
*/
public static final String DISALLOW_RECORD_AUDIO = "no_record_audio";
/**
* Specifies if a user is not allowed to use the camera.
*
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
* @see #getUserRestrictions()
* @hide
*/
public static final String DISALLOW_CAMERA = "no_camera";
/**
* Allows apps in the parent profile to handle web links from the managed profile.
*

View File

@@ -738,10 +738,11 @@ public class UserManagerService extends IUserManager.Stub {
mBaseUserRestrictions.put(userId, newRestrictions);
}
mCachedEffectiveUserRestrictions.put(
userId, computeEffectiveUserRestrictionsRL(userId));
final Bundle effective = computeEffectiveUserRestrictionsRL(userId);
applyUserRestrictionsRL(userId, mBaseUserRestrictions.get(userId), prevRestrictions);
mCachedEffectiveUserRestrictions.put(userId, effective);
applyUserRestrictionsRL(userId, effective, prevRestrictions);
}
@GuardedBy("mRestrictionsLock")

View File

@@ -1016,6 +1016,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
// DO NOT call it while taking the "this" lock, which could cause a dead lock.
private void handlePackagesChanged(String packageName, int userHandle) {
boolean removed = false;
if (VERBOSE_LOG) Slog.d(LOG_TAG, "Handling package changes for user " + userHandle);
@@ -1042,7 +1043,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
if (removed) {
validatePasswordOwnerLocked(policy);
syncDeviceCapabilitiesLocked(policy);
saveSettingsLocked(policy.mUserHandle);
}
@@ -1061,6 +1061,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
}
if (removed) {
synchronized (mUserManagerInternal.getUserRestrictionsLock()) {
synchronized (DevicePolicyManagerService.this) {
mUserManagerInternal.updateEffectiveUserRestrictionsRL(
userHandle);
}
}
}
}
/**
@@ -1682,7 +1690,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
void removeActiveAdminLocked(final ComponentName adminReceiver, int userHandle) {
void removeActiveAdminLocked(final ComponentName adminReceiver, final int userHandle) {
final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
if (admin != null) {
synchronized (this) {
@@ -1701,7 +1709,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
policy.mAdminList.remove(admin);
policy.mAdminMap.remove(adminReceiver);
validatePasswordOwnerLocked(policy);
syncDeviceCapabilitiesLocked(policy);
if (doProxyCleanup) {
resetGlobalProxyLocked(getUserData(userHandle));
}
@@ -1709,6 +1716,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
updateMaximumTimeToLockLocked(policy);
policy.mRemovingAdmins.remove(adminReceiver);
}
synchronized (mUserManagerInternal.getUserRestrictionsLock()) {
synchronized (DevicePolicyManagerService.this) {
mUserManagerInternal.updateEffectiveUserRestrictionsRL(
userHandle);
}
}
}
});
}
@@ -2022,7 +2035,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
validatePasswordOwnerLocked(policy);
syncDeviceCapabilitiesLocked(policy);
updateMaximumTimeToLockLocked(policy);
updateLockTaskPackagesLocked(policy.mLockTaskPackages, userHandle);
if (policy.mStatusBarDisabled) {
@@ -2089,31 +2101,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
/**
* Pushes down policy information to the system for any policies related to general device
* capabilities that need to be enforced by lower level services (e.g. Camera services).
*/
void syncDeviceCapabilitiesLocked(DevicePolicyData policy) {
// Ensure the status of the camera is synced down to the system. Interested native services
// should monitor this value and act accordingly.
String cameraPropertyForUser = SYSTEM_PROP_DISABLE_CAMERA_PREFIX + policy.mUserHandle;
boolean systemState = mInjector.systemPropertiesGetBoolean(cameraPropertyForUser, false);
boolean cameraDisabled = getCameraDisabled(null, policy.mUserHandle);
if (cameraDisabled != systemState) {
long token = mInjector.binderClearCallingIdentity();
try {
String value = cameraDisabled ? "1" : "0";
if (VERBOSE_LOG) {
Slog.v(LOG_TAG, "Change in camera state ["
+ cameraPropertyForUser + "] = " + value);
}
mInjector.systemPropertiesSet(cameraPropertyForUser, value);
} finally {
mInjector.binderRestoreCallingIdentity(token);
}
}
}
@VisibleForTesting
void systemReady(int phase) {
if (!mHasFeature) {
@@ -4328,13 +4315,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
/**
* The system property used to share the state of the camera. The native camera service
* is expected to read this property and act accordingly. The userId should be appended
* to this key.
*/
public static final String SYSTEM_PROP_DISABLE_CAMERA_PREFIX = "sys.secpolicy.camera.off_";
/**
* Disables all device cameras according to the specified admin.
*/
@@ -4352,7 +4332,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
ap.disableCamera = disabled;
saveSettingsLocked(userHandle);
}
syncDeviceCapabilitiesLocked(getUserData(userHandle));
}
// Tell the user manager that the restrictions have changed.
synchronized (mUserManagerInternal.getUserRestrictionsLock()) {
synchronized (this) {
if (isDeviceOwner(who)) {
mUserManagerInternal.updateEffectiveUserRestrictionsForAllUsersRL();
} else {
mUserManagerInternal.updateEffectiveUserRestrictionsRL(userHandle);
}
}
}
}
@@ -4370,7 +4359,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
return (admin != null) ? admin.disableCamera : false;
}
// First, see if DO has set it. If so, it's device-wide.
final ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
if (deviceOwner != null && deviceOwner.disableCamera) {
return true;
}
// Then check each device admin on the user.
DevicePolicyData policy = getUserData(userHandle);
// Determine whether or not the device camera is disabled for any active admins.
final int N = policy.mAdminList.size();
@@ -4404,7 +4399,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
ap.disabledKeyguardFeatures = which;
saveSettingsLocked(userHandle);
}
syncDeviceCapabilitiesLocked(getUserData(userHandle));
}
}
@@ -5036,7 +5030,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES);
ap.trustAgentInfos.put(agent.flattenToString(), new TrustAgentInfo(args));
saveSettingsLocked(userHandle);
syncDeviceCapabilitiesLocked(getUserData(userHandle));
}
}
@@ -5602,6 +5595,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
// DO NOT call it while taking the "this" lock, which could cause a dead lock.
@Override
public void setUserRestriction(ComponentName who, String key, boolean enabledFromThisOwner) {
Preconditions.checkNotNull(who, "ComponentName is null");
@@ -5612,7 +5606,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
ActiveAdmin activeAdmin =
getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
boolean isDeviceOwner = isDeviceOwner(who);
final boolean isDeviceOwner = isDeviceOwner(who);
if (!isDeviceOwner && userHandle != UserHandle.USER_SYSTEM
&& DEVICE_OWNER_USER_RESTRICTIONS.contains(key)) {
throw new SecurityException(
@@ -6463,8 +6457,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
deviceOwner == null ? null : deviceOwner.userRestrictions;
final Bundle profileOwnerRestrictions =
profileOwner == null ? null : profileOwner.userRestrictions;
final boolean cameraDisabled = getCameraDisabled(null, userId);
if (deviceOwnerRestrictions == null && profileOwnerRestrictions == null) {
if (deviceOwnerRestrictions == null && profileOwnerRestrictions == null
&& !cameraDisabled) {
// No restrictions to merge.
return inBundle;
}
@@ -6473,6 +6469,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
UserRestrictionsUtils.merge(composed, deviceOwnerRestrictions);
UserRestrictionsUtils.merge(composed, profileOwnerRestrictions);
// Also merge in the camera restriction.
if (cameraDisabled) {
composed.putBoolean(UserManager.DISALLOW_CAMERA, true);
}
return composed;
}
}