Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3b2c9426 authored by Kholoud Mohamed's avatar Kholoud Mohamed
Browse files

Migrate screen capture disabled to the policy engine

Bug: 251401809
Bug: 273494642
Test: btest android.devicepolicy.cts.DeviceManagementCoexistenceTest
Test: atest MixedManagedProfileOwnerTest#testCreateAdminSupportIntent
Test: atest MixedManagedProfileOwnerTest#testScreenCaptureDisabled_assist
Test: atest MixedManagedProfileOwnerTest#testScreenCaptureDisabled_assist_allowedPrimaryUser
Test: btest android.devicepolicy.cts.ScreenCaptureDisabledTest
Change-Id: I9da7b026e937a9e729777b4de613b319a4084418
parent 9a5003db
Loading
Loading
Loading
Loading
+38 −3
Original line number Diff line number Diff line
@@ -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,11 +79,23 @@ 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 !mScreenCaptureDisallowedUsers.contains(userHandle)
                    && !mScreenCaptureDisallowedUsers.contains(UserHandle.USER_ALL);
        }
    }

    public int getScreenCaptureDisallowedUser() {
        synchronized (mLock) {
@@ -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();
            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());
+1 −2
Original line number Diff line number Diff line
@@ -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();
            }
+74 −31
Original line number Diff line number Diff line
@@ -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,25 +8656,49 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            }
        }
        synchronized (getLockObject()) {
            ActiveAdmin ap;
            if (isPermissionCheckFlagEnabled()) {
        if (isPolicyEngineForFinanceFlagEnabled()) {
            int callerUserId = Binder.getCallingUserHandle().getIdentifier();
            int targetUserId = parent ? getProfileParentId(callerUserId) : callerUserId;
                ap = enforcePermissionAndGetEnforcingAdmin(
            EnforcingAdmin admin = enforcePermissionAndGetEnforcingAdmin(
                    who, MANAGE_DEVICE_POLICY_SCREEN_CAPTURE, caller.getPackageName(),
                        targetUserId).getActiveAdmin();
                    targetUserId);
            if ((parent && isProfileOwnerOfOrganizationOwnedDevice(caller))
                    || isDefaultDeviceOwner(caller)) {
                if (disabled) {
                    mDevicePolicyEngine.setGlobalPolicy(
                            PolicyDefinition.SCREEN_CAPTURE_DISABLED,
                            admin,
                            new BooleanPolicyValue(disabled));
                } else {
                ap = getParentOfAdminIfRequired(
                        getProfileOwnerOrDefaultDeviceOwnerLocked(caller.getUserId()), parent);
                    mDevicePolicyEngine.removeGlobalPolicy(
                            PolicyDefinition.SCREEN_CAPTURE_DISABLED,
                            admin);
                }
            } else {
                if (disabled) {
                    mDevicePolicyEngine.setLocalPolicy(
                            PolicyDefinition.SCREEN_CAPTURE_DISABLED,
                            admin,
                            new BooleanPolicyValue(disabled),
                            callerUserId);
                } else {
                    mDevicePolicyEngine.removeLocalPolicy(
                            PolicyDefinition.SCREEN_CAPTURE_DISABLED,
                            admin,
                            callerUserId);
                }
            }
        } else {
            synchronized (getLockObject()) {
                ActiveAdmin ap = getParentOfAdminIfRequired(
                        getProfileOwnerOrDefaultDeviceOwnerLocked(caller.getUserId()), parent);
                if (ap.disableScreenCapture != disabled) {
                    ap.disableScreenCapture = disabled;
                    saveSettingsLocked(caller.getUserId());
                    pushScreenCapturePolicy(caller.getUserId());
                }
            }
        }
        DevicePolicyEventLogger
                .createEvent(DevicePolicyEnums.SET_SCREEN_CAPTURE_DISABLED)
                .setAdmin(caller.getPackageName())
@@ -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,8 +8768,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            Preconditions.checkCallAuthorization(
                    isProfileOwnerOfOrganizationOwnedDevice(getCallerIdentity().getUserId()));
        }
        if (isPolicyEngineForFinanceFlagEnabled()) {
            Boolean disallowed = mDevicePolicyEngine.getResolvedPolicy(
                    PolicyDefinition.SCREEN_CAPTURE_DISABLED,
                    userHandle);
            return disallowed != null && disallowed;
        } else {
            return !mPolicyCache.isScreenCaptureAllowed(userHandle);
        }
    }
    private void updateScreenCaptureDisabled() {
        mHandler.post(() -> {
@@ -16306,6 +16339,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                return result;
            }
        } else if (DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE.equals(restriction)) {
            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();
@@ -16320,6 +16362,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                        }
                    }
                }
            }
        } else if (DevicePolicyManager.POLICY_DISABLE_CAMERA.equals(restriction)) {
            if (isPolicyEngineForFinanceFlagEnabled()) {
                PolicyDefinition<Boolean> policyDefinition =
@@ -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,
+10 −0
Original line number Diff line number Diff line
@@ -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);
+31 −0
Original line number Diff line number Diff line
@@ -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);
            }
        });
    }
}