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

Commit 8bb98ec7 authored by Victor Gabriel Savu's avatar Victor Gabriel Savu
Browse files

Add a first version of the setPolicy

The implementation of setPolicy in DevicePolicyManager is just
temporary, this CL focuses on the API of setPolicy itself.

FCRS_CODE: mdmwdjabuee391

Bug: 433950213
Flag: android.app.admin.flags.policy_streamlining
Test: CTS
Change-Id: I57b5a0f4ce68b24deaf052c5e9c5955a400a8637
parent 6fa77f07
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -8555,6 +8555,7 @@ package android.app.admin {
    method public boolean setPermittedCrossProfileNotificationListeners(@NonNull android.content.ComponentName, @Nullable java.util.List<java.lang.String>);
    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_INPUT_METHODS, conditional=true) public boolean setPermittedInputMethods(@Nullable android.content.ComponentName, java.util.List<java.lang.String>);
    method public void setPersonalAppsSuspended(@NonNull android.content.ComponentName, boolean);
    method @FlaggedApi("android.app.admin.flags.policy_streamlining") public <T> void setPolicy(@NonNull android.app.admin.PolicyIdentifier<T>, int, @Nullable T);
    method public void setPreferentialNetworkServiceConfigs(@NonNull java.util.List<android.app.admin.PreferentialNetworkServiceConfig>);
    method public void setPreferentialNetworkServiceEnabled(boolean);
    method public void setProfileEnabled(@NonNull android.content.ComponentName);
@@ -8760,6 +8761,9 @@ package android.app.admin {
    field public static final int PERSONAL_APPS_SUSPENDED_PROFILE_TIMEOUT = 2; // 0x2
    field public static final String POLICY_DISABLE_CAMERA = "policy_disable_camera";
    field public static final String POLICY_DISABLE_SCREEN_CAPTURE = "policy_disable_screen_capture";
    field @FlaggedApi("android.app.admin.flags.policy_streamlining") public static final int POLICY_SCOPE_DEVICE = 2; // 0x2
    field @FlaggedApi("android.app.admin.flags.policy_streamlining") public static final int POLICY_SCOPE_PARENT = 3; // 0x3
    field @FlaggedApi("android.app.admin.flags.policy_streamlining") public static final int POLICY_SCOPE_USER = 1; // 0x1
    field public static final int PRIVATE_DNS_MODE_OFF = 1; // 0x1
    field public static final int PRIVATE_DNS_MODE_OPPORTUNISTIC = 2; // 0x2
    field public static final int PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = 3; // 0x3
@@ -8872,6 +8876,10 @@ package android.app.admin {
    field public static final int PACKAGE_POLICY_BLOCKLIST = 1; // 0x1
  }
  @FlaggedApi("android.app.admin.flags.policy_streamlining") public final class PolicyIdentifier<T> {
    field @FlaggedApi("android.app.admin.flags.policy_streamlining") @NonNull public static final android.app.admin.PolicyIdentifier<java.lang.Boolean> SCREEN_CAPTURE_DISABLED;
  }
  public abstract class PolicyUpdateReceiver extends android.content.BroadcastReceiver {
    ctor public PolicyUpdateReceiver();
    method public void onPolicyChanged(@NonNull android.content.Context, @NonNull String, @NonNull android.os.Bundle, @NonNull android.app.admin.TargetUser, @NonNull android.app.admin.PolicyUpdateResult);
+6 −0
Original line number Diff line number Diff line
@@ -616,6 +616,7 @@ package android.app.admin {
    method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void resetShouldAllowBypassingDevicePolicyManagementRoleQualificationState();
    method @RequiresPermission(allOf={android.Manifest.permission.MANAGE_DEVICE_ADMINS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void setActiveAdmin(@NonNull android.content.ComponentName, boolean, int);
    method @FlaggedApi("android.app.admin.flags.provisioning_context_parameter") @RequiresPermission(allOf={android.Manifest.permission.MANAGE_DEVICE_ADMINS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void setActiveAdmin(@NonNull android.content.ComponentName, boolean, int, @Nullable String);
    method public void setBooleanPolicy(@NonNull String, int, boolean);
    method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public boolean setDeviceOwner(@NonNull android.content.ComponentName, int);
    method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public boolean setDeviceOwnerOnly(@NonNull android.content.ComponentName, int);
    method public void setDeviceOwnerType(@NonNull android.content.ComponentName, int);
@@ -714,6 +715,11 @@ package android.app.admin {
    ctor public PackagePolicyKey(@NonNull String, @NonNull String);
  }

  @FlaggedApi("android.app.admin.flags.policy_streamlining") public final class PolicyIdentifier<T> {
    ctor public PolicyIdentifier(@NonNull String);
    method @NonNull public String getId();
  }

  public final class PolicyState<V> implements android.os.Parcelable {
    method @NonNull public android.app.admin.ResolutionMechanism<V> getResolutionMechanism();
  }
+79 −0
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ import static android.app.admin.flags.Flags.FLAG_REMOVE_MANAGED_PROFILE_ENABLED;
import static android.app.admin.flags.Flags.FLAG_CROSS_PROFILE_WIDGET_PROVIDER_BULK_APIS;
import static android.app.admin.flags.Flags.FLAG_SECONDARY_LOCKSCREEN_API_ENABLED;
import static android.app.admin.flags.Flags.FLAG_SPLIT_CREATE_MANAGED_PROFILE_ENABLED;
import static android.app.admin.flags.Flags.FLAG_POLICY_STREAMLINING;
import static android.app.admin.flags.Flags.onboardingBugreportV2Enabled;
import static android.app.admin.flags.Flags.onboardingConsentlessBugreports;
import static android.content.Intent.LOCAL_FLAG_FROM_SYSTEM;
@@ -18515,4 +18516,82 @@ public class DevicePolicyManager {
        }
        return HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED;
    }
    /**
     * Flag used by {@link #setPolicy} to apply the policy to the same user as the context user.
     */
    @FlaggedApi(FLAG_POLICY_STREAMLINING)
    public static final int POLICY_SCOPE_USER = 0x0001;
    /**
     * Flag used by {@link #setPolicy} to apply the policy to the entire device.
     */
    @FlaggedApi(FLAG_POLICY_STREAMLINING)
    public static final int POLICY_SCOPE_DEVICE = 0x0002;
    /**
     * Flag used by {@link #setPolicy} to apply the policy to the parent user of the context user.
     */
    @FlaggedApi(FLAG_POLICY_STREAMLINING)
    public static final int POLICY_SCOPE_PARENT = 0x0003;
    /**
     * Possible policy scopes
     *
     * @hide
     */
    @IntDef(prefix = { "POLICY_SCOPE_" }, value = {
            POLICY_SCOPE_USER,
            POLICY_SCOPE_DEVICE,
            POLICY_SCOPE_PARENT,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface PolicyScope {}
    /**
     * Sets the given policy.
     *
     * @param id The policy identifier to update. It must be one of the values inside
     * {@link DevicePolicyIdentifier}.
     * @param scope The scope the policy will apply to.
     * @param value The value of the policy.
     * @throws SecurityException If the caller does not have sufficient permissions to set the
     * specified id. Check the documentation of individual identifiers for more details.
     * @throws IllegalArgumentException The passed value failed validation. Check the
     * documentation of individual identifiers for more details.
     */
    @FlaggedApi(FLAG_POLICY_STREAMLINING)
    @UserHandleAware
    public <T> void setPolicy(
            @NonNull PolicyIdentifier<T> id,
            @PolicyScope int scope,
            @Nullable T value) {
        throwIfParentInstance("setPolicy");
        if (mService != null) {
            // TODO(b/434655549): Implement as a generic handler.
            if (id.equals(PolicyIdentifier.SCREEN_CAPTURE_DISABLED)) {
                if (value == null) return; // No way to clear the policy.
                // TODO(b/434615264): Actually use the scope here.
                setScreenCaptureDisabled(null, (Boolean) value);
            } else {
                throw new IllegalArgumentException("Unhandled policy " + id);
            }
        }
    }
    /**
     * Template free version of setPolicy for booleans.
     *
     * @hide
    */
    @TestApi
    @SuppressWarnings("UnflaggedApi") // @TestApi without associated feature.
    public void setBooleanPolicy(
            @NonNull String key,
            @PolicyScope int scope,
            boolean value) {
        // TODO(b/434920631): Remove this method and use {@link #setPolicy} in tests directly.
        setPolicy(new PolicyIdentifier<Boolean>(key), scope, Boolean.valueOf(value));
    }
}
+92 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.app.admin;

import static android.app.admin.flags.Flags.FLAG_POLICY_STREAMLINING;

import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.TestApi;

/**
 * Represents a type safe identifier for a policy. Use it as a key for
 * {@link DevicePolicyManager.setPolicy setPolicy} and related APIs.
 *
 * @param <T> Represents the type of the value that is associated with this identifier.
 */
@FlaggedApi(FLAG_POLICY_STREAMLINING)
public final class PolicyIdentifier<T> {
    private final String mId;

    /** Create an instance of PolicyIdentifier. Should only be used to create the static
     * definitions below.
     *
     * @hide
     */
    @TestApi
    public PolicyIdentifier(@NonNull String id) {
        this.mId = id;
    }

    /**
     * Get the string representation of this identifier.
     *
     * @return The string representation of this identifier
     *
     * @hide
     */
    @NonNull
    @TestApi
    public String getId() {
        return mId;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof PolicyIdentifier)) return false;
        PolicyIdentifier<?> that = (PolicyIdentifier<?>) o;
        return mId.equals(that.mId);
    }

    @Override
    public int hashCode() {
        return mId.hashCode();
    }

    @Override
    @NonNull
    public String toString() {
        return mId;
    }

    /* Compatible with the existing definition */
    private static final String SCREEN_CAPTURE_DISABLED_KEY =
            DevicePolicyIdentifiers.SCREEN_CAPTURE_DISABLED_POLICY;

    /**
     * Policy that controls whether the screen capture is disabled. Disabling
     * screen capture also prevents the content from being shown on display devices that do not have
     * a secure video output. See {@link android.view.Display#FLAG_SECURE} for more details about
     * secure surfaces and secure displays.
     */
    // TODO(b/433951378): Document or annotate who can call this and what errors can be thrown.
    @NonNull
    @FlaggedApi(FLAG_POLICY_STREAMLINING)
    public static final PolicyIdentifier<Boolean> SCREEN_CAPTURE_DISABLED =
                new PolicyIdentifier<>(SCREEN_CAPTURE_DISABLED_KEY);
}
+8 −0
Original line number Diff line number Diff line
@@ -476,3 +476,11 @@ flag {
  description: "Add bulk APIs for cross profile widget providers"
  bug: "421053737"
}

flag {
  name: "policy_streamlining"
  is_exported: true
  namespace: "enterprise"
  description: "Enable the policy streamlining APIs."
  bug: "434919316"
}