diff options
5 files changed, 154 insertions, 36 deletions
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java index c681b884d2ed..522ee341010b 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java @@ -25,7 +25,9 @@ import android.util.SparseIntArray; import com.android.internal.annotations.GuardedBy; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -48,6 +50,13 @@ public class DevicePolicyCacheImpl extends DevicePolicyCache { @GuardedBy("mLock") private int mScreenCaptureDisallowedUser = UserHandle.USER_NULL; + /** + * Indicates if screen capture is disallowed on a specific user or all users if + * it contains {@link UserHandle#USER_ALL}. + */ + @GuardedBy("mLock") + private Set<Integer> mScreenCaptureDisallowedUsers = new HashSet<>(); + @GuardedBy("mLock") private final SparseIntArray mPasswordQuality = new SparseIntArray(); @@ -70,9 +79,21 @@ public class DevicePolicyCacheImpl extends DevicePolicyCache { @Override public boolean isScreenCaptureAllowed(int userHandle) { + if (DevicePolicyManagerService.isPolicyEngineForFinanceFlagEnabled()) { + return isScreenCaptureAllowedInPolicyEngine(userHandle); + } else { + synchronized (mLock) { + return mScreenCaptureDisallowedUser != UserHandle.USER_ALL + && mScreenCaptureDisallowedUser != userHandle; + } + } + } + + private boolean isScreenCaptureAllowedInPolicyEngine(int userHandle) { + // This won't work if resolution mechanism is not strictest applies, but it's ok for now. synchronized (mLock) { - return mScreenCaptureDisallowedUser != UserHandle.USER_ALL - && mScreenCaptureDisallowedUser != userHandle; + return !mScreenCaptureDisallowedUsers.contains(userHandle) + && !mScreenCaptureDisallowedUsers.contains(UserHandle.USER_ALL); } } @@ -88,6 +109,16 @@ public class DevicePolicyCacheImpl extends DevicePolicyCache { } } + public void setScreenCaptureDisallowedUser(int userHandle, boolean disallowed) { + synchronized (mLock) { + if (disallowed) { + mScreenCaptureDisallowedUsers.add(userHandle); + } else { + mScreenCaptureDisallowedUsers.remove(userHandle); + } + } + } + @Override public int getPasswordQuality(@UserIdInt int userHandle) { synchronized (mLock) { @@ -151,7 +182,11 @@ public class DevicePolicyCacheImpl extends DevicePolicyCache { synchronized (mLock) { pw.println("Device policy cache:"); pw.increaseIndent(); - pw.println("Screen capture disallowed user: " + mScreenCaptureDisallowedUser); + if (DevicePolicyManagerService.isPolicyEngineForFinanceFlagEnabled()) { + pw.println("Screen capture disallowed users: " + mScreenCaptureDisallowedUsers); + } else { + pw.println("Screen capture disallowed user: " + mScreenCaptureDisallowedUser); + } pw.println("Password quality: " + mPasswordQuality); pw.println("Permission policy: " + mPermissionPolicy); pw.println("Admin can grant sensors permission: " + mCanGrantSensorsPermissions.get()); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java index 0c4830afafcc..641a03b931c4 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java @@ -546,8 +546,7 @@ final class DevicePolicyEngine { if (hasLocalPolicyLocked(policyDefinition, userId)) { resolvedValue = getLocalPolicyStateLocked( policyDefinition, userId).getCurrentResolvedPolicy(); - } - if (hasGlobalPolicyLocked(policyDefinition)) { + } else if (hasGlobalPolicyLocked(policyDefinition)) { resolvedValue = getGlobalPolicyStateLocked( policyDefinition).getCurrentResolvedPolicy(); } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 3578b16d62c6..97987096fa86 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -8642,7 +8642,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } CallerIdentity caller; - if (isPermissionCheckFlagEnabled()) { + if (isPolicyEngineForFinanceFlagEnabled()) { caller = getCallerIdentity(who, callerPackage); } else { Objects.requireNonNull(who, "ComponentName is null"); @@ -8656,23 +8656,47 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - synchronized (getLockObject()) { - ActiveAdmin ap; - if (isPermissionCheckFlagEnabled()) { - int callerUserId = Binder.getCallingUserHandle().getIdentifier(); - int targetUserId = parent ? getProfileParentId(callerUserId) : callerUserId; - ap = enforcePermissionAndGetEnforcingAdmin( - who, MANAGE_DEVICE_POLICY_SCREEN_CAPTURE, caller.getPackageName(), - targetUserId).getActiveAdmin(); + if (isPolicyEngineForFinanceFlagEnabled()) { + int callerUserId = Binder.getCallingUserHandle().getIdentifier(); + int targetUserId = parent ? getProfileParentId(callerUserId) : callerUserId; + EnforcingAdmin admin = enforcePermissionAndGetEnforcingAdmin( + who, MANAGE_DEVICE_POLICY_SCREEN_CAPTURE, caller.getPackageName(), + targetUserId); + if ((parent && isProfileOwnerOfOrganizationOwnedDevice(caller)) + || isDefaultDeviceOwner(caller)) { + if (disabled) { + mDevicePolicyEngine.setGlobalPolicy( + PolicyDefinition.SCREEN_CAPTURE_DISABLED, + admin, + new BooleanPolicyValue(disabled)); + } else { + mDevicePolicyEngine.removeGlobalPolicy( + PolicyDefinition.SCREEN_CAPTURE_DISABLED, + admin); + } } else { - ap = getParentOfAdminIfRequired( - getProfileOwnerOrDefaultDeviceOwnerLocked(caller.getUserId()), parent); + if (disabled) { + mDevicePolicyEngine.setLocalPolicy( + PolicyDefinition.SCREEN_CAPTURE_DISABLED, + admin, + new BooleanPolicyValue(disabled), + callerUserId); + } else { + mDevicePolicyEngine.removeLocalPolicy( + PolicyDefinition.SCREEN_CAPTURE_DISABLED, + admin, + callerUserId); + } } - - if (ap.disableScreenCapture != disabled) { - ap.disableScreenCapture = disabled; - saveSettingsLocked(caller.getUserId()); - pushScreenCapturePolicy(caller.getUserId()); + } else { + synchronized (getLockObject()) { + ActiveAdmin ap = getParentOfAdminIfRequired( + getProfileOwnerOrDefaultDeviceOwnerLocked(caller.getUserId()), parent); + if (ap.disableScreenCapture != disabled) { + ap.disableScreenCapture = disabled; + saveSettingsLocked(caller.getUserId()); + pushScreenCapturePolicy(caller.getUserId()); + } } } DevicePolicyEventLogger @@ -8686,6 +8710,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // 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) { + if (isPolicyEngineForFinanceFlagEnabled()) { + return; + } // Update screen capture device-wide if disabled by the DO or COPE PO on the parent profile. // TODO(b/261999445): remove ActiveAdmin admin; @@ -8727,8 +8754,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } /** - * Returns whether or not screen capture is disabled for a given admin, or disabled for any - * active admin (if given admin is null). + * Returns whether or not screen capture is disabled for any active admin. */ @Override public boolean getScreenCaptureDisabled(ComponentName who, int userHandle, boolean parent) { @@ -8742,7 +8768,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Preconditions.checkCallAuthorization( isProfileOwnerOfOrganizationOwnedDevice(getCallerIdentity().getUserId())); } - return !mPolicyCache.isScreenCaptureAllowed(userHandle); + if (isPolicyEngineForFinanceFlagEnabled()) { + Boolean disallowed = mDevicePolicyEngine.getResolvedPolicy( + PolicyDefinition.SCREEN_CAPTURE_DISABLED, + userHandle); + return disallowed != null && disallowed; + } else { + return !mPolicyCache.isScreenCaptureAllowed(userHandle); + } } private void updateScreenCaptureDisabled() { @@ -16306,17 +16339,27 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return result; } } else if (DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE.equals(restriction)) { - synchronized (getLockObject()) { - final DevicePolicyData policy = getUserData(userId); - final int N = policy.mAdminList.size(); - for (int i = 0; i < N; i++) { - final ActiveAdmin admin = policy.mAdminList.get(i); - if (admin.disableScreenCapture) { - result = new Bundle(); - result.putInt(Intent.EXTRA_USER_ID, userId); - result.putParcelable(DevicePolicyManager.EXTRA_DEVICE_ADMIN, - admin.info.getComponent()); - return result; + if (isPolicyEngineForFinanceFlagEnabled()) { + Boolean value = mDevicePolicyEngine.getResolvedPolicy( + PolicyDefinition.SCREEN_CAPTURE_DISABLED, userId); + if (value != null && value) { + result = new Bundle(); + result.putInt(Intent.EXTRA_USER_ID, userId); + return result; + } + } else { + synchronized (getLockObject()) { + final DevicePolicyData policy = getUserData(userId); + final int N = policy.mAdminList.size(); + for (int i = 0; i < N; i++) { + final ActiveAdmin admin = policy.mAdminList.get(i); + if (admin.disableScreenCapture) { + result = new Bundle(); + result.putInt(Intent.EXTRA_USER_ID, userId); + result.putParcelable(DevicePolicyManager.EXTRA_DEVICE_ADMIN, + admin.info.getComponent()); + return result; + } } } } @@ -23646,7 +23689,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { DEFAULT_VALUE_PERMISSION_BASED_ACCESS_FLAG); } - private boolean isPolicyEngineForFinanceFlagEnabled() { + static boolean isPolicyEngineForFinanceFlagEnabled() { return DeviceConfig.getBoolean( NAMESPACE_DEVICE_POLICY_MANAGER, ENABLE_DEVICE_POLICY_ENGINE_FOR_FINANCE_FLAG, diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java index 43a2c9bbf5c5..17c84f9916dd 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java @@ -315,6 +315,14 @@ final class PolicyDefinition<V> { (Set<String> value, Context context, Integer userId, PolicyKey policyKey) -> true, new StringSetPolicySerializer()); + + static PolicyDefinition<Boolean> SCREEN_CAPTURE_DISABLED = new PolicyDefinition<>( + new NoArgsPolicyKey(DevicePolicyIdentifiers.SCREEN_CAPTURE_DISABLED_POLICY), + TRUE_MORE_RESTRICTIVE, + /* flags= */ 0, + PolicyEnforcerCallbacks::setScreenCaptureDisabled, + new BooleanPolicySerializer()); + private static final Map<String, PolicyDefinition<?>> POLICY_DEFINITIONS = new HashMap<>(); private static Map<String, Integer> USER_RESTRICTION_FLAGS = new HashMap<>(); @@ -342,6 +350,8 @@ final class PolicyDefinition<V> { GENERIC_ACCOUNT_MANAGEMENT_DISABLED); POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.PERMITTED_INPUT_METHODS_POLICY, PERMITTED_INPUT_METHODS); + POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.SCREEN_CAPTURE_DISABLED_POLICY, + SCREEN_CAPTURE_DISABLED); // User Restriction Policies USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_MODIFY_ACCOUNTS, /* flags= */ 0); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java index 289098e87550..816a9848d5b3 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java @@ -19,6 +19,7 @@ package com.android.server.devicepolicy; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AppGlobals; +import android.app.admin.DevicePolicyCache; import android.app.admin.DevicePolicyManager; import android.app.admin.IntentFilterPolicyKey; import android.app.admin.LockTaskPolicy; @@ -35,13 +36,16 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.os.Binder; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.UserHandle; import android.permission.AdminPermissionControlParams; import android.permission.PermissionControllerManager; import android.provider.Settings; import android.util.ArraySet; import android.util.Slog; +import android.view.IWindowManager; +import com.android.internal.os.BackgroundThread; import com.android.server.LocalServices; import com.android.server.pm.UserManagerInternal; import com.android.server.utils.Slogf; @@ -244,4 +248,31 @@ final class PolicyEnforcerCallbacks { packageName, hide != null && hide, userId); })); } + + static boolean setScreenCaptureDisabled( + @Nullable Boolean disabled, @NonNull Context context, int userId, + @NonNull PolicyKey policyKey) { + Binder.withCleanCallingIdentity(() -> { + DevicePolicyCache cache = DevicePolicyCache.getInstance(); + if (cache instanceof DevicePolicyCacheImpl) { + DevicePolicyCacheImpl parsedCache = (DevicePolicyCacheImpl) cache; + parsedCache.setScreenCaptureDisallowedUser( + userId, disabled != null && disabled); + updateScreenCaptureDisabled(); + } + }); + return true; + } + + private static void updateScreenCaptureDisabled() { + BackgroundThread.getHandler().post(() -> { + try { + IWindowManager.Stub + .asInterface(ServiceManager.getService(Context.WINDOW_SERVICE)) + .refreshScreenCaptureDisabled(); + } catch (RemoteException e) { + Slogf.w(LOG_TAG, "Unable to notify WindowManager.", e); + } + }); + } } |