Merge "Make screen capture per-device DO and COPE" into tm-dev am: c170d9adf0

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17070865

Change-Id: Iea6489f8f59ec59275031e2e4df3d1685d09ffb8
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Alex Johnston
2022-04-22 09:31:59 +00:00
committed by Automerger Merge Worker
9 changed files with 87 additions and 51 deletions

View File

@@ -41,8 +41,7 @@ public abstract class DevicePolicyCache {
/** /**
* See {@link DevicePolicyManager#getScreenCaptureDisabled} * See {@link DevicePolicyManager#getScreenCaptureDisabled}
*/ */
public abstract boolean isScreenCaptureAllowed(@UserIdInt int userHandle, public abstract boolean isScreenCaptureAllowed(@UserIdInt int userHandle);
boolean ownerCanAddInternalSystemWindow);
/** /**
* Caches {@link DevicePolicyManager#getPasswordQuality(android.content.ComponentName)} of the * Caches {@link DevicePolicyManager#getPasswordQuality(android.content.ComponentName)} of the
@@ -70,8 +69,7 @@ public abstract class DevicePolicyCache {
private static final EmptyDevicePolicyCache INSTANCE = new EmptyDevicePolicyCache(); private static final EmptyDevicePolicyCache INSTANCE = new EmptyDevicePolicyCache();
@Override @Override
public boolean isScreenCaptureAllowed(int userHandle, public boolean isScreenCaptureAllowed(int userHandle) {
boolean ownerCanAddInternalSystemWindow) {
return true; return true;
} }

View File

@@ -249,7 +249,7 @@ interface IWindowManager
* Set whether screen capture is disabled for all windows of a specific user from * Set whether screen capture is disabled for all windows of a specific user from
* the device policy cache. * the device policy cache.
*/ */
void refreshScreenCaptureDisabled(int userId); void refreshScreenCaptureDisabled();
// These can only be called with the SET_ORIENTATION permission. // These can only be called with the SET_ORIENTATION permission.
/** /**

View File

@@ -3331,7 +3331,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
} }
userId = activity.mUserId; userId = activity.mUserId;
} }
return DevicePolicyCache.getInstance().isScreenCaptureAllowed(userId, false); return DevicePolicyCache.getInstance().isScreenCaptureAllowed(userId);
} }
private void onLocalVoiceInteractionStartedLocked(IBinder activity, private void onLocalVoiceInteractionStartedLocked(IBinder activity,

View File

@@ -643,9 +643,9 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
} }
} }
void setSecureSurfaceState(int userId) { void refreshSecureSurfaceState() {
forAllWindows((w) -> { forAllWindows((w) -> {
if (w.mHasSurface && userId == w.mShowUserId) { if (w.mHasSurface) {
w.mWinAnimator.setSecureLocked(w.isSecureLocked()); w.mWinAnimator.setSecureLocked(w.isSecureLocked());
} }
}, true /* traverseTopToBottom */); }, true /* traverseTopToBottom */);

View File

@@ -2009,15 +2009,15 @@ public class WindowManagerService extends IWindowManager.Stub
* the device policy cache. * the device policy cache.
*/ */
@Override @Override
public void refreshScreenCaptureDisabled(int userId) { public void refreshScreenCaptureDisabled() {
int callingUid = Binder.getCallingUid(); int callingUid = Binder.getCallingUid();
if (callingUid != SYSTEM_UID) { if (callingUid != SYSTEM_UID) {
throw new SecurityException("Only system can call refreshScreenCaptureDisabled."); throw new SecurityException("Only system can call refreshScreenCaptureDisabled.");
} }
synchronized (mGlobalLock) { synchronized (mGlobalLock) {
// Update secure surface for all windows belonging to this user. // Refresh secure surface for all windows.
mRoot.setSecureSurfaceState(userId); mRoot.refreshSecureSurfaceState();
} }
} }

View File

@@ -2040,8 +2040,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if ((mAttrs.flags & WindowManager.LayoutParams.FLAG_SECURE) != 0) { if ((mAttrs.flags & WindowManager.LayoutParams.FLAG_SECURE) != 0) {
return true; return true;
} }
return !DevicePolicyCache.getInstance().isScreenCaptureAllowed(mShowUserId, return !DevicePolicyCache.getInstance().isScreenCaptureAllowed(mShowUserId);
mOwnerCanAddInternalSystemWindow);
} }
/** /**

View File

@@ -18,6 +18,7 @@ package com.android.server.devicepolicy;
import android.annotation.UserIdInt; import android.annotation.UserIdInt;
import android.app.admin.DevicePolicyCache; import android.app.admin.DevicePolicyCache;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.os.UserHandle;
import android.util.IndentingPrintWriter; import android.util.IndentingPrintWriter;
import android.util.SparseBooleanArray; import android.util.SparseBooleanArray;
import android.util.SparseIntArray; import android.util.SparseIntArray;
@@ -37,8 +38,12 @@ public class DevicePolicyCacheImpl extends DevicePolicyCache {
*/ */
private final Object mLock = new Object(); private final Object mLock = new Object();
/**
* Indicates which user is screen capture disallowed on. Can be {@link UserHandle#USER_NULL},
* {@link UserHandle#USER_ALL} or a concrete user ID.
*/
@GuardedBy("mLock") @GuardedBy("mLock")
private final SparseBooleanArray mScreenCaptureDisabled = new SparseBooleanArray(); private int mScreenCaptureDisallowedUser = UserHandle.USER_NULL;
@GuardedBy("mLock") @GuardedBy("mLock")
private final SparseIntArray mPasswordQuality = new SparseIntArray(); private final SparseIntArray mPasswordQuality = new SparseIntArray();
@@ -57,7 +62,6 @@ public class DevicePolicyCacheImpl extends DevicePolicyCache {
public void onUserRemoved(int userHandle) { public void onUserRemoved(int userHandle) {
synchronized (mLock) { synchronized (mLock) {
mScreenCaptureDisabled.delete(userHandle);
mPasswordQuality.delete(userHandle); mPasswordQuality.delete(userHandle);
mPermissionPolicy.delete(userHandle); mPermissionPolicy.delete(userHandle);
mCanGrantSensorsPermissions.delete(userHandle); mCanGrantSensorsPermissions.delete(userHandle);
@@ -65,15 +69,22 @@ public class DevicePolicyCacheImpl extends DevicePolicyCache {
} }
@Override @Override
public boolean isScreenCaptureAllowed(int userHandle, boolean ownerCanAddInternalSystemWindow) { public boolean isScreenCaptureAllowed(int userHandle) {
synchronized (mLock) { synchronized (mLock) {
return !mScreenCaptureDisabled.get(userHandle) || ownerCanAddInternalSystemWindow; return mScreenCaptureDisallowedUser != UserHandle.USER_ALL
&& mScreenCaptureDisallowedUser != userHandle;
} }
} }
public void setScreenCaptureAllowed(int userHandle, boolean allowed) { public int getScreenCaptureDisallowedUser() {
synchronized (mLock) { synchronized (mLock) {
mScreenCaptureDisabled.put(userHandle, !allowed); return mScreenCaptureDisallowedUser;
}
}
public void setScreenCaptureDisallowedUser(int userHandle) {
synchronized (mLock) {
mScreenCaptureDisallowedUser = userHandle;
} }
} }
@@ -125,7 +136,7 @@ public class DevicePolicyCacheImpl extends DevicePolicyCache {
public void dump(IndentingPrintWriter pw) { public void dump(IndentingPrintWriter pw) {
pw.println("Device policy cache:"); pw.println("Device policy cache:");
pw.increaseIndent(); pw.increaseIndent();
pw.println("Screen capture disabled: " + mScreenCaptureDisabled.toString()); pw.println("Screen capture disallowed user: " + mScreenCaptureDisallowedUser);
pw.println("Password quality: " + mPasswordQuality.toString()); pw.println("Password quality: " + mPasswordQuality.toString());
pw.println("Permission policy: " + mPermissionPolicy.toString()); pw.println("Permission policy: " + mPermissionPolicy.toString());
pw.println("Admin can grant sensors permission: " pw.println("Admin can grant sensors permission: "

View File

@@ -1963,6 +1963,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
mOwners.removeProfileOwner(userHandle); mOwners.removeProfileOwner(userHandle);
mOwners.writeProfileOwner(userHandle); mOwners.writeProfileOwner(userHandle);
pushScreenCapturePolicy(userHandle);
DevicePolicyData policy = mUserData.get(userHandle); DevicePolicyData policy = mUserData.get(userHandle);
if (policy != null) { if (policy != null) {
@@ -3183,8 +3184,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override @Override
void handleStartUser(int userId) { void handleStartUser(int userId) {
updateScreenCaptureDisabled(userId, synchronized (getLockObject()) {
getScreenCaptureDisabled(null, userId, false)); pushScreenCapturePolicy(userId);
}
pushUserRestrictions(userId); pushUserRestrictions(userId);
// When system user is started (device boot), load cache for all users. // When system user is started (device boot), load cache for all users.
// This is to mitigate the potential race between loading the cache and keyguard // This is to mitigate the potential race between loading the cache and keyguard
@@ -6919,7 +6921,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
notifyResetProtectionPolicyChanged(frpAgentUid); notifyResetProtectionPolicyChanged(frpAgentUid);
} }
mLockSettingsInternal.refreshStrongAuthTimeout(parentId); mLockSettingsInternal.refreshStrongAuthTimeout(parentId);
updateScreenCaptureDisabled(parentId, getScreenCaptureDisabled(null, parentId, false));
Slogf.i(LOG_TAG, "Cleaning up device-wide policies done."); Slogf.i(LOG_TAG, "Cleaning up device-wide policies done.");
} }
@@ -7686,10 +7687,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (ap.disableScreenCapture != disabled) { if (ap.disableScreenCapture != disabled) {
ap.disableScreenCapture = disabled; ap.disableScreenCapture = disabled;
saveSettingsLocked(caller.getUserId()); saveSettingsLocked(caller.getUserId());
final int affectedUserId = parent pushScreenCapturePolicy(caller.getUserId());
? getProfileParentId(caller.getUserId())
: caller.getUserId();
updateScreenCaptureDisabled(affectedUserId, disabled);
} }
} }
DevicePolicyEventLogger DevicePolicyEventLogger
@@ -7699,6 +7697,38 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
.write(); .write();
} }
// Push the screen capture policy for a given userId. If screen capture is disabled by the
// DO or COPE PO on the parent profile, then this takes precedence as screen capture will
// be disabled device-wide.
private void pushScreenCapturePolicy(int adminUserId) {
// Update screen capture device-wide if disabled by the DO or COPE PO on the parent profile.
ActiveAdmin admin =
getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceParentLocked(
UserHandle.USER_SYSTEM);
if (admin != null && admin.disableScreenCapture) {
setScreenCaptureDisabled(UserHandle.USER_ALL);
} else {
// Otherwise, update screen capture only for the calling user.
admin = getProfileOwnerAdminLocked(adminUserId);
if (admin != null && admin.disableScreenCapture) {
setScreenCaptureDisabled(adminUserId);
} else {
setScreenCaptureDisabled(UserHandle.USER_NULL);
}
}
}
// Set the latest screen capture policy, overriding any existing ones.
// userHandle can be one of USER_ALL, USER_NULL or a concrete userId.
private void setScreenCaptureDisabled(int userHandle) {
int current = mPolicyCache.getScreenCaptureDisallowedUser();
if (userHandle == current) {
return;
}
mPolicyCache.setScreenCaptureDisallowedUser(userHandle);
updateScreenCaptureDisabled();
}
/** /**
* Returns whether or not screen capture is disabled for a given admin, or disabled for any * Returns whether or not screen capture is disabled for a given admin, or disabled for any
* active admin (if given admin is null). * active admin (if given admin is null).
@@ -7708,7 +7738,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) { if (!mHasFeature) {
return false; return false;
} }
final CallerIdentity caller = getCallerIdentity(who); final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle)); Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle));
@@ -7716,29 +7745,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Preconditions.checkCallAuthorization( Preconditions.checkCallAuthorization(
isProfileOwnerOfOrganizationOwnedDevice(getCallerIdentity().getUserId())); isProfileOwnerOfOrganizationOwnedDevice(getCallerIdentity().getUserId()));
} }
return !mPolicyCache.isScreenCaptureAllowed(userHandle);
synchronized (getLockObject()) {
if (who != null) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent);
return (admin != null) && admin.disableScreenCapture;
}
final int affectedUserId = parent ? getProfileParentId(userHandle) : userHandle;
List<ActiveAdmin> admins = getActiveAdminsForAffectedUserLocked(affectedUserId);
for (ActiveAdmin admin: admins) {
if (admin.disableScreenCapture) {
return true;
}
}
return false;
}
} }
private void updateScreenCaptureDisabled(int userHandle, boolean disabled) { private void updateScreenCaptureDisabled() {
mPolicyCache.setScreenCaptureAllowed(userHandle, !disabled);
mHandler.post(() -> { mHandler.post(() -> {
try { try {
mInjector.getIWindowManager().refreshScreenCaptureDisabled(userHandle); mInjector.getIWindowManager().refreshScreenCaptureDisabled();
} catch (RemoteException e) { } catch (RemoteException e) {
Slogf.w(LOG_TAG, "Unable to notify WindowManager.", e); Slogf.w(LOG_TAG, "Unable to notify WindowManager.", e);
} }
@@ -8690,6 +8703,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
} }
ActiveAdmin getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceLocked(int userId) { ActiveAdmin getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceLocked(int userId) {
ensureLocked();
ActiveAdmin admin = getDeviceOwnerAdminLocked(); ActiveAdmin admin = getDeviceOwnerAdminLocked();
if (admin == null) { if (admin == null) {
admin = getProfileOwnerOfOrganizationOwnedDeviceLocked(userId); admin = getProfileOwnerOfOrganizationOwnedDeviceLocked(userId);
@@ -8697,6 +8711,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return admin; return admin;
} }
ActiveAdmin getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceParentLocked(int userId) {
ensureLocked();
ActiveAdmin admin = getDeviceOwnerAdminLocked();
if (admin != null) {
return admin;
}
admin = getProfileOwnerOfOrganizationOwnedDeviceLocked(userId);
return admin != null ? admin.getParentActiveAdmin() : null;
}
@Override @Override
public void clearDeviceOwner(String packageName) { public void clearDeviceOwner(String packageName) {
Objects.requireNonNull(packageName, "packageName is null"); Objects.requireNonNull(packageName, "packageName is null");
@@ -15151,6 +15175,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
saveSettingsLocked(userHandle); saveSettingsLocked(userHandle);
updateMaximumTimeToLockLocked(userHandle); updateMaximumTimeToLockLocked(userHandle);
policy.mRemovingAdmins.remove(adminReceiver); policy.mRemovingAdmins.remove(adminReceiver);
pushScreenCapturePolicy(userHandle);
Slogf.i(LOG_TAG, "Device admin " + adminReceiver + " removed from user " + userHandle); Slogf.i(LOG_TAG, "Device admin " + adminReceiver + " removed from user " + userHandle);
} }

View File

@@ -4992,8 +4992,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
.thenReturn(12345 /* some UID in user 0 */); .thenReturn(12345 /* some UID in user 0 */);
// Make personal apps look suspended // Make personal apps look suspended
dpms.getUserData(UserHandle.USER_SYSTEM).mAppsSuspended = true; dpms.getUserData(UserHandle.USER_SYSTEM).mAppsSuspended = true;
// Screen capture
clearInvocations(getServices().iwindowManager); dpm.setScreenCaptureDisabled(admin1, true);
dpm.wipeData(0); dpm.wipeData(0);
verify(getServices().userManagerInternal).removeUserEvenWhenDisallowed(CALLER_USER_HANDLE); verify(getServices().userManagerInternal).removeUserEvenWhenDisallowed(CALLER_USER_HANDLE);
@@ -5004,6 +5004,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(getServices().userManager).setUserRestriction( verify(getServices().userManager).setUserRestriction(
UserManager.DISALLOW_ADD_USER, false, UserHandle.SYSTEM); UserManager.DISALLOW_ADD_USER, false, UserHandle.SYSTEM);
clearInvocations(getServices().iwindowManager);
// Some device-wide policies are getting cleaned-up after the user is removed. // Some device-wide policies are getting cleaned-up after the user is removed.
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID; mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
sendBroadcastWithUser(dpms, Intent.ACTION_USER_REMOVED, CALLER_USER_HANDLE); sendBroadcastWithUser(dpms, Intent.ACTION_USER_REMOVED, CALLER_USER_HANDLE);
@@ -5020,9 +5022,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
MockUtils.checkIntentAction( MockUtils.checkIntentAction(
DevicePolicyManager.ACTION_RESET_PROTECTION_POLICY_CHANGED), DevicePolicyManager.ACTION_RESET_PROTECTION_POLICY_CHANGED),
MockUtils.checkUserHandle(UserHandle.USER_SYSTEM)); MockUtils.checkUserHandle(UserHandle.USER_SYSTEM));
// Refresh strong auth timeout and screen capture // Refresh strong auth timeout
verify(getServices().lockSettingsInternal).refreshStrongAuthTimeout(UserHandle.USER_SYSTEM); verify(getServices().lockSettingsInternal).refreshStrongAuthTimeout(UserHandle.USER_SYSTEM);
verify(getServices().iwindowManager).refreshScreenCaptureDisabled(UserHandle.USER_SYSTEM); // Refresh screen capture
verify(getServices().iwindowManager).refreshScreenCaptureDisabled();
// Unsuspend personal apps // Unsuspend personal apps
verify(getServices().packageManagerInternal) verify(getServices().packageManagerInternal)
.unsuspendForSuspendingPackage(PLATFORM_PACKAGE_NAME, UserHandle.USER_SYSTEM); .unsuspendForSuspendingPackage(PLATFORM_PACKAGE_NAME, UserHandle.USER_SYSTEM);