Loading core/java/android/app/admin/StringSetIntersection.java 0 → 100644 +80 −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 android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; import java.util.Set; /** * Class to identify a intersection resolution mechanism for {@code Set<String>} policies, it's * used to resolve the enforced policy when being set by multiple admins (see {@link * PolicyState#getResolutionMechanism()}). * * @hide */ public final class StringSetIntersection extends ResolutionMechanism<Set<String>> { /** * Intersection resolution for policies represented {@code Set<String>} which resolves as the * intersection of all sets. */ @NonNull public static final StringSetIntersection STRING_SET_INTERSECTION = new StringSetIntersection(); @Override public boolean equals(@Nullable Object o) { if (this == o) return true; return o != null && getClass() == o.getClass(); } @Override public int hashCode() { return 0; } @Override public String toString() { return "StringSetIntersection {}"; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(@NonNull Parcel dest, int flags) {} @NonNull public static final Parcelable.Creator<StringSetIntersection> CREATOR = new Parcelable.Creator<StringSetIntersection>() { @Override public StringSetIntersection createFromParcel(Parcel source) { return new StringSetIntersection(); } @Override public StringSetIntersection[] newArray(int size) { return new StringSetIntersection[size]; } }; } core/java/android/app/admin/flags/flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -412,3 +412,13 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "use_policy_intersection_for_permitted_input_methods" namespace: "enterprise" description: "When deciding on permitted input methods, use policy intersection instead of last recorded policy." bug: "340914586" metadata { purpose: PURPOSE_BUGFIX } } services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java +4 −1 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.app.admin.PackagePolicyKey; import android.app.admin.PolicyKey; import android.app.admin.PolicyValue; import android.app.admin.UserRestrictionPolicyKey; import android.app.admin.flags.Flags; import android.content.ComponentName; import android.content.Context; import android.content.IntentFilter; Loading Loading @@ -282,7 +283,9 @@ final class PolicyDefinition<V> { static PolicyDefinition<Set<String>> PERMITTED_INPUT_METHODS = new PolicyDefinition<>( new NoArgsPolicyKey(DevicePolicyIdentifiers.PERMITTED_INPUT_METHODS_POLICY), new MostRecent<>(), (Flags.usePolicyIntersectionForPermittedInputMethods() ? new StringSetIntersection() : new MostRecent<>()), POLICY_FLAG_LOCAL_ONLY_POLICY | POLICY_FLAG_INHERITABLE, PolicyEnforcerCallbacks::noOp, new PackageSetPolicySerializer()); Loading services/devicepolicy/java/com/android/server/devicepolicy/StringSetIntersection.java 0 → 100644 +59 −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 com.android.server.devicepolicy; import android.annotation.NonNull; import android.app.admin.PolicyValue; import android.app.admin.PackageSetPolicyValue; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Objects; import java.util.Set; final class StringSetIntersection extends ResolutionMechanism<Set<String>> { @Override PolicyValue<Set<String>> resolve( @NonNull LinkedHashMap<EnforcingAdmin, PolicyValue<Set<String>>> adminPolicies) { Objects.requireNonNull(adminPolicies); Set<String> intersectionOfPolicies = null; for (PolicyValue<Set<String>> policy : adminPolicies.values()) { if (intersectionOfPolicies == null) { intersectionOfPolicies = new HashSet<>(policy.getValue()); } else { intersectionOfPolicies.retainAll(policy.getValue()); } } if (intersectionOfPolicies == null) { return null; } // Note that the resulting set below may be empty, but that's fine: // particular policy should decide what is the meaning of an empty set. return new PackageSetPolicyValue(intersectionOfPolicies); } @Override android.app.admin.StringSetIntersection getParcelableResolutionMechanism() { return new android.app.admin.StringSetIntersection(); } @Override public String toString() { return "StringSetIntersection {}"; } } Loading
core/java/android/app/admin/StringSetIntersection.java 0 → 100644 +80 −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 android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; import java.util.Set; /** * Class to identify a intersection resolution mechanism for {@code Set<String>} policies, it's * used to resolve the enforced policy when being set by multiple admins (see {@link * PolicyState#getResolutionMechanism()}). * * @hide */ public final class StringSetIntersection extends ResolutionMechanism<Set<String>> { /** * Intersection resolution for policies represented {@code Set<String>} which resolves as the * intersection of all sets. */ @NonNull public static final StringSetIntersection STRING_SET_INTERSECTION = new StringSetIntersection(); @Override public boolean equals(@Nullable Object o) { if (this == o) return true; return o != null && getClass() == o.getClass(); } @Override public int hashCode() { return 0; } @Override public String toString() { return "StringSetIntersection {}"; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(@NonNull Parcel dest, int flags) {} @NonNull public static final Parcelable.Creator<StringSetIntersection> CREATOR = new Parcelable.Creator<StringSetIntersection>() { @Override public StringSetIntersection createFromParcel(Parcel source) { return new StringSetIntersection(); } @Override public StringSetIntersection[] newArray(int size) { return new StringSetIntersection[size]; } }; }
core/java/android/app/admin/flags/flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -412,3 +412,13 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "use_policy_intersection_for_permitted_input_methods" namespace: "enterprise" description: "When deciding on permitted input methods, use policy intersection instead of last recorded policy." bug: "340914586" metadata { purpose: PURPOSE_BUGFIX } }
services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java +4 −1 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.app.admin.PackagePolicyKey; import android.app.admin.PolicyKey; import android.app.admin.PolicyValue; import android.app.admin.UserRestrictionPolicyKey; import android.app.admin.flags.Flags; import android.content.ComponentName; import android.content.Context; import android.content.IntentFilter; Loading Loading @@ -282,7 +283,9 @@ final class PolicyDefinition<V> { static PolicyDefinition<Set<String>> PERMITTED_INPUT_METHODS = new PolicyDefinition<>( new NoArgsPolicyKey(DevicePolicyIdentifiers.PERMITTED_INPUT_METHODS_POLICY), new MostRecent<>(), (Flags.usePolicyIntersectionForPermittedInputMethods() ? new StringSetIntersection() : new MostRecent<>()), POLICY_FLAG_LOCAL_ONLY_POLICY | POLICY_FLAG_INHERITABLE, PolicyEnforcerCallbacks::noOp, new PackageSetPolicySerializer()); Loading
services/devicepolicy/java/com/android/server/devicepolicy/StringSetIntersection.java 0 → 100644 +59 −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 com.android.server.devicepolicy; import android.annotation.NonNull; import android.app.admin.PolicyValue; import android.app.admin.PackageSetPolicyValue; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Objects; import java.util.Set; final class StringSetIntersection extends ResolutionMechanism<Set<String>> { @Override PolicyValue<Set<String>> resolve( @NonNull LinkedHashMap<EnforcingAdmin, PolicyValue<Set<String>>> adminPolicies) { Objects.requireNonNull(adminPolicies); Set<String> intersectionOfPolicies = null; for (PolicyValue<Set<String>> policy : adminPolicies.values()) { if (intersectionOfPolicies == null) { intersectionOfPolicies = new HashSet<>(policy.getValue()); } else { intersectionOfPolicies.retainAll(policy.getValue()); } } if (intersectionOfPolicies == null) { return null; } // Note that the resulting set below may be empty, but that's fine: // particular policy should decide what is the meaning of an empty set. return new PackageSetPolicyValue(intersectionOfPolicies); } @Override android.app.admin.StringSetIntersection getParcelableResolutionMechanism() { return new android.app.admin.StringSetIntersection(); } @Override public String toString() { return "StringSetIntersection {}"; } }