Skip to content

Commit 9b10fd9

Browse files
Rubin XuAndroid Build Coastguard Worker
authored andcommitted
Handle screen capture disabled state for multiple users
Before this fix, the framework use one single integer to track screen capture disabled policy across the device. This can be either a real userId, or the symbolic USER_ALL or USER_NULL for all users or no user. This has the problem that it can't represent policies from more than one admin (or policies from both the admin and its parent). In addition, due to the way DevicePolicyManagerService refreshes policies, when a non-managed user is started, its default policy state overrides any existing policy, causing screen capture to be no longer disabled. Fix this by properly tracking the policy for each user in an set. We still use USER_ALL in the set to represent screen capture being disabled for all users. In Android 14, the screen capture logic is migrated to policy engine which already contains this fix. Bug: 305664128 Test: ScreenCaptureDisabledTest Test: FrameworksServicesTests:DevicePolicyManagerTest Test: DevicePolicyManagerServiceMigrationTest Test: MixedDeviceOwnerTest#testScreenCaptureDisabled_assist MixedProfileOwnerTest#testScreenCaptureDisabled_assist MixedManagedProfileOwnerTest#testScreenCaptureDisabled_assist Test: MixedManagedProfileOwnerTest#testScreenCaptureDisabled_assist_allowedPrimaryUser Test: MixedDeviceOwnerTest#testCreateAdminSupportIntent MixedProfileOwnerTest#testCreateAdminSupportIntent MixedManagedProfileOwnerTest#testCreateAdminSupportIntent (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:5f3db5ae9b9cf69c8a4ea73b6ed49ce9d49ba223) Merged-In: Ib016b740927003f8bd81992f24c722c29ac723b5 Change-Id: Ib016b740927003f8bd81992f24c722c29ac723b5
1 parent a035450 commit 9b10fd9

3 files changed

Lines changed: 33 additions & 23 deletions

File tree

services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525

2626
import com.android.internal.annotations.GuardedBy;
2727

28+
import java.util.HashSet;
29+
import java.util.Set;
30+
2831
/**
2932
* Implementation of {@link DevicePolicyCache}, to which {@link DevicePolicyManagerService} pushes
3033
* policies.
@@ -45,6 +48,13 @@ public class DevicePolicyCacheImpl extends DevicePolicyCache {
4548
@GuardedBy("mLock")
4649
private int mScreenCaptureDisallowedUser = UserHandle.USER_NULL;
4750

51+
/**
52+
* Indicates if screen capture is disallowed on a specific user or all users if
53+
* it contains {@link UserHandle#USER_ALL}.
54+
*/
55+
@GuardedBy("mLock")
56+
private Set<Integer> mScreenCaptureDisallowedUsers = new HashSet<>();
57+
4858
@GuardedBy("mLock")
4959
private final SparseIntArray mPasswordQuality = new SparseIntArray();
5060

@@ -71,8 +81,8 @@ public void onUserRemoved(int userHandle) {
7181
@Override
7282
public boolean isScreenCaptureAllowed(int userHandle) {
7383
synchronized (mLock) {
74-
return mScreenCaptureDisallowedUser != UserHandle.USER_ALL
75-
&& mScreenCaptureDisallowedUser != userHandle;
84+
return !mScreenCaptureDisallowedUsers.contains(userHandle)
85+
&& !mScreenCaptureDisallowedUsers.contains(UserHandle.USER_ALL);
7686
}
7787
}
7888

@@ -88,6 +98,16 @@ public void setScreenCaptureDisallowedUser(int userHandle) {
8898
}
8999
}
90100

101+
public void setScreenCaptureDisallowedUser(int userHandle, boolean disallowed) {
102+
synchronized (mLock) {
103+
if (disallowed) {
104+
mScreenCaptureDisallowedUsers.add(userHandle);
105+
} else {
106+
mScreenCaptureDisallowedUsers.remove(userHandle);
107+
}
108+
}
109+
}
110+
91111
@Override
92112
public int getPasswordQuality(@UserIdInt int userHandle) {
93113
synchronized (mLock) {
@@ -136,7 +156,7 @@ public void setAdminCanGrantSensorsPermissions(@UserIdInt int userId, boolean ca
136156
public void dump(IndentingPrintWriter pw) {
137157
pw.println("Device policy cache:");
138158
pw.increaseIndent();
139-
pw.println("Screen capture disallowed user: " + mScreenCaptureDisallowedUser);
159+
pw.println("Screen capture disallowed users: " + mScreenCaptureDisallowedUsers);
140160
pw.println("Password quality: " + mPasswordQuality.toString());
141161
pw.println("Permission policy: " + mPermissionPolicy.toString());
142162
pw.println("Admin can grant sensors permission: "

services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7707,30 +7707,20 @@ public void setScreenCaptureDisabled(ComponentName who, boolean disabled, boolea
77077707
// be disabled device-wide.
77087708
private void pushScreenCapturePolicy(int adminUserId) {
77097709
// Update screen capture device-wide if disabled by the DO or COPE PO on the parent profile.
7710-
ActiveAdmin admin =
7711-
getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceParentLocked(
7710+
// Always do this regardless which user this method is called with. Probably a little
7711+
// wasteful but still safe.
7712+
ActiveAdmin admin = getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceParentLocked(
77127713
UserHandle.USER_SYSTEM);
7713-
if (admin != null && admin.disableScreenCapture) {
7714-
setScreenCaptureDisabled(UserHandle.USER_ALL);
7715-
} else {
7716-
// Otherwise, update screen capture only for the calling user.
7717-
admin = getProfileOwnerAdminLocked(adminUserId);
7718-
if (admin != null && admin.disableScreenCapture) {
7719-
setScreenCaptureDisabled(adminUserId);
7720-
} else {
7721-
setScreenCaptureDisabled(UserHandle.USER_NULL);
7722-
}
7723-
}
7714+
setScreenCaptureDisabled(UserHandle.USER_ALL, admin != null && admin.disableScreenCapture);
7715+
// Update screen capture only for the calling user.
7716+
admin = getProfileOwnerAdminLocked(adminUserId);
7717+
setScreenCaptureDisabled(adminUserId, admin != null && admin.disableScreenCapture);
77247718
}
77257719

77267720
// Set the latest screen capture policy, overriding any existing ones.
77277721
// userHandle can be one of USER_ALL, USER_NULL or a concrete userId.
7728-
private void setScreenCaptureDisabled(int userHandle) {
7729-
int current = mPolicyCache.getScreenCaptureDisallowedUser();
7730-
if (userHandle == current) {
7731-
return;
7732-
}
7733-
mPolicyCache.setScreenCaptureDisallowedUser(userHandle);
7722+
private void setScreenCaptureDisabled(int userHandle, boolean disabled) {
7723+
mPolicyCache.setScreenCaptureDisallowedUser(userHandle, disabled);
77347724
updateScreenCaptureDisabled();
77357725
}
77367726

services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5056,7 +5056,7 @@ public void testWipeDataManagedProfileOnOrganizationOwnedDevice() throws Excepti
50565056
// Refresh strong auth timeout
50575057
verify(getServices().lockSettingsInternal).refreshStrongAuthTimeout(UserHandle.USER_SYSTEM);
50585058
// Refresh screen capture
5059-
verify(getServices().iwindowManager).refreshScreenCaptureDisabled();
5059+
verify(getServices().iwindowManager, times(2)).refreshScreenCaptureDisabled();
50605060
// Unsuspend personal apps
50615061
verify(getServices().packageManagerInternal)
50625062
.unsuspendForSuspendingPackage(PLATFORM_PACKAGE_NAME, UserHandle.USER_SYSTEM);

0 commit comments

Comments
 (0)