1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.app.admin;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.util.ArraySet;
24 
25 import java.lang.annotation.Retention;
26 import java.lang.annotation.RetentionPolicy;
27 import java.util.Collections;
28 import java.util.Objects;
29 import java.util.Set;
30 
31 
32 /**
33  * A generic class that defines which APK packages are in scope for some device policy.
34  * <p>
35  * The packages can be defined using either an allowlist or a blocklist.
36  * In allowlist mode, it could optionally include all system packages
37  * that meet the specific criteria of the device policy in question.
38  */
39 public final class PackagePolicy implements Parcelable {
40 
41     /**
42      * PackagePolicy type indicator for {@link PackagePolicy}
43      * <p>
44      * This constant indicates that all packages are allowed except for the packages returned by
45      * {@link PackagePolicy#getPackageNames()}, which acts as a denylist.
46      * @see #PACKAGE_POLICY_ALLOWLIST_AND_SYSTEM
47      * @see #PACKAGE_POLICY_ALLOWLIST
48      */
49     public static final int PACKAGE_POLICY_BLOCKLIST = 1;
50 
51     /**
52      * PackagePolicy type indicator for {@link PackagePolicy}
53      * <p>
54      * This constant indicates system packages are allowed in addition to the packages returned by
55      * {@link PackagePolicy#getPackageNames()}, which acts as an allowlist.
56      *
57      * <p>Functions that accept {@link PackagePolicy} will further clarify
58      * how this policy is interpreted.
59      *
60      * @see #PACKAGE_POLICY_BLOCKLIST
61      * @see #PACKAGE_POLICY_ALLOWLIST
62      */
63     public static final int PACKAGE_POLICY_ALLOWLIST_AND_SYSTEM = 2;
64 
65     /**
66      * PackagePolicy type indicator for {@link PackagePolicy}
67      * <p>
68      * This constant indicates that all packages are denied except for the packages returned by
69      * {@link PackagePolicy#getPackageNames()}, which acts as an allowlist.
70      *
71      * @see #PACKAGE_POLICY_BLOCKLIST
72      * @see #PACKAGE_POLICY_ALLOWLIST_AND_SYSTEM
73      */
74     public static final int PACKAGE_POLICY_ALLOWLIST = 3;
75 
76     /**
77      *
78      * @hide
79      */
80     @Retention(RetentionPolicy.SOURCE)
81     @IntDef(prefix = {"PACKAGE_POLICY_"}, value = {
82             PACKAGE_POLICY_BLOCKLIST,
83             PACKAGE_POLICY_ALLOWLIST_AND_SYSTEM,
84             PACKAGE_POLICY_ALLOWLIST
85     })
86     public @interface PackagePolicyType {}
87 
88     private @PackagePolicyType int mPolicyType;
89 
90     private ArraySet<String> mPackageNames;
91 
92     /**
93      * Create the package policy
94      * @param policyType indicates how to interpret this policy
95 
96      * @see PackagePolicy#PackagePolicy(int, Set)
97      */
PackagePolicy(@ackagePolicyType int policyType)98     public PackagePolicy(@PackagePolicyType int policyType) {
99         this(policyType, Collections.emptySet());
100     }
101 
102     /**
103      * Create the package policy
104      * @param policyType indicates how to interpret this policy
105      * @param packageNames allowlist or a denylist, based on policyType
106      */
PackagePolicy(@ackagePolicyType int policyType, @NonNull Set<String> packageNames)107     public PackagePolicy(@PackagePolicyType int policyType, @NonNull Set<String> packageNames) {
108         if (policyType != PACKAGE_POLICY_BLOCKLIST
109                 && policyType != PACKAGE_POLICY_ALLOWLIST_AND_SYSTEM
110                 && policyType != PACKAGE_POLICY_ALLOWLIST) {
111             throw new IllegalArgumentException("Invalid policy type");
112         }
113         mPolicyType = policyType;
114         mPackageNames = new ArraySet<>(packageNames);
115     }
116 
PackagePolicy(Parcel in)117     private PackagePolicy(Parcel in) {
118         mPolicyType = in.readInt();
119         mPackageNames = (ArraySet<String>) in.readArraySet(null);
120     }
121 
122     /**
123      * Returns the current policy type
124      */
getPolicyType()125     public @PackagePolicyType int getPolicyType() {
126         return mPolicyType;
127     }
128 
129     /**
130      * Returns the list of packages to use as an allow/deny list based on policy type
131      */
132     @NonNull
getPackageNames()133     public Set<String> getPackageNames() {
134         return Collections.unmodifiableSet(mPackageNames);
135     }
136 
137     /**
138      * Evaluates the packageName provided against this policy to determine if the package should be
139      * allowed.
140      *
141      * If the policy type is {@link #PACKAGE_POLICY_ALLOWLIST_AND_SYSTEM},
142      * the systemPackage will be used in addition to package names of this policy's
143      * {@link #getPackageNames()}
144      *
145      * @param packageName  the name of the package to test
146      * @param systemPackages list of packages identified as system packages
147      * @return true if the package is allowed, false if the package is denied
148      * @hide
149      */
isPackageAllowed(@onNull String packageName, @NonNull Set<String> systemPackages)150     public boolean isPackageAllowed(@NonNull String packageName,
151             @NonNull Set<String> systemPackages) {
152         if (mPolicyType == PACKAGE_POLICY_BLOCKLIST) {
153             return !mPackageNames.contains(packageName);
154         }
155         return mPackageNames.contains(packageName)
156                 || (mPolicyType == PACKAGE_POLICY_ALLOWLIST_AND_SYSTEM
157                       && systemPackages.contains(packageName));
158     }
159 
160     /**
161      * @see Parcelable.Creator
162      */
163     @NonNull
164     public static final Creator<PackagePolicy> CREATOR = new Creator<PackagePolicy>() {
165         @Override
166         public PackagePolicy createFromParcel(Parcel in) {
167             return new PackagePolicy(in);
168         }
169 
170         @Override
171         public PackagePolicy[] newArray(int size) {
172             return new PackagePolicy[size];
173         }
174     };
175 
176     @Override
writeToParcel(@onNull Parcel dest, int flags)177     public void writeToParcel(@NonNull Parcel dest, int flags) {
178         dest.writeInt(mPolicyType);
179         dest.writeArraySet(mPackageNames);
180     }
181 
182     @Override
equals(Object thatObject)183     public boolean equals(Object thatObject) {
184         if (this == thatObject) {
185             return true;
186         }
187         if (!(thatObject instanceof PackagePolicy)) {
188             return false;
189         }
190         PackagePolicy that = (PackagePolicy) thatObject;
191         return mPolicyType == that.mPolicyType && mPackageNames.equals(that.mPackageNames);
192     }
193 
194     @Override
hashCode()195     public int hashCode() {
196         return Objects.hash(mPolicyType, mPackageNames);
197     }
198 
199     @Override
describeContents()200     public int describeContents() {
201         return 0;
202     }
203 
204 }
205