1 /*
2  * Copyright (C) 2020 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.content.pm.parsing.component;
18 
19 import android.annotation.Nullable;
20 import android.content.pm.PermissionInfo;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.text.TextUtils;
24 import android.util.ArraySet;
25 
26 import com.android.internal.annotations.VisibleForTesting;
27 import com.android.internal.util.DataClass;
28 import com.android.internal.util.Parcelling;
29 import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
30 import com.android.internal.util.Parcelling.BuiltIn.ForStringSet;
31 
32 import java.util.Locale;
33 import java.util.Set;
34 
35 /** @hide */
36 public class ParsedPermission extends ParsedComponent {
37 
38     private static ForStringSet sForStringSet = Parcelling.Cache.getOrCreate(ForStringSet.class);
39 
40     @Nullable
41     String backgroundPermission;
42     @Nullable
43     @DataClass.ParcelWith(ForInternedString.class)
44     private String group;
45     int requestRes;
46     int protectionLevel;
47     boolean tree;
48     @Nullable
49     private ParsedPermissionGroup parsedPermissionGroup;
50     @Nullable
51     Set<String> knownCerts;
52 
53     @VisibleForTesting
ParsedPermission()54     public ParsedPermission() {
55     }
56 
ParsedPermission(ParsedPermission other)57     public ParsedPermission(ParsedPermission other) {
58         super(other);
59         this.backgroundPermission = other.backgroundPermission;
60         this.group = other.group;
61         this.requestRes = other.requestRes;
62         this.protectionLevel = other.protectionLevel;
63         this.tree = other.tree;
64         this.parsedPermissionGroup = other.parsedPermissionGroup;
65     }
66 
setGroup(String group)67     public ParsedPermission setGroup(String group) {
68         this.group = TextUtils.safeIntern(group);
69         return this;
70     }
71 
setFlags(int flags)72     public ParsedPermission setFlags(int flags) {
73         this.flags = flags;
74         return this;
75     }
76 
isRuntime()77     public boolean isRuntime() {
78         return getProtection() == PermissionInfo.PROTECTION_DANGEROUS;
79     }
80 
isAppOp()81     public boolean isAppOp() {
82         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0;
83     }
84 
85     @PermissionInfo.Protection
getProtection()86     public int getProtection() {
87         return protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
88     }
89 
getProtectionFlags()90     public int getProtectionFlags() {
91         return protectionLevel & ~PermissionInfo.PROTECTION_MASK_BASE;
92     }
93 
getKnownCerts()94     public @Nullable Set<String> getKnownCerts() {
95         return knownCerts;
96     }
97 
setKnownCert(String knownCert)98     protected void setKnownCert(String knownCert) {
99         // Convert the provided digest to upper case for consistent Set membership
100         // checks when verifying the signing certificate digests of requesting apps.
101         this.knownCerts = Set.of(knownCert.toUpperCase(Locale.US));
102     }
103 
setKnownCerts(String[] knownCerts)104     protected void setKnownCerts(String[] knownCerts) {
105         this.knownCerts = new ArraySet<>();
106         for (String knownCert : knownCerts) {
107             this.knownCerts.add(knownCert.toUpperCase(Locale.US));
108         }
109     }
110 
calculateFootprint()111     public int calculateFootprint() {
112         int size = getName().length();
113         if (getNonLocalizedLabel() != null) {
114             size += getNonLocalizedLabel().length();
115         }
116         return size;
117     }
118 
toString()119     public String toString() {
120         return "Permission{"
121                 + Integer.toHexString(System.identityHashCode(this))
122                 + " " + getName() + "}";
123     }
124 
125     @Override
describeContents()126     public int describeContents() {
127         return 0;
128     }
129 
130     @Override
writeToParcel(Parcel dest, int flags)131     public void writeToParcel(Parcel dest, int flags) {
132         super.writeToParcel(dest, flags);
133         dest.writeString(this.backgroundPermission);
134         dest.writeString(this.group);
135         dest.writeInt(this.requestRes);
136         dest.writeInt(this.protectionLevel);
137         dest.writeBoolean(this.tree);
138         dest.writeParcelable(this.parsedPermissionGroup, flags);
139         sForStringSet.parcel(knownCerts, dest, flags);
140     }
141 
ParsedPermission(Parcel in)142     protected ParsedPermission(Parcel in) {
143         super(in);
144         // We use the boot classloader for all classes that we load.
145         final ClassLoader boot = Object.class.getClassLoader();
146         this.backgroundPermission = in.readString();
147         this.group = in.readString();
148         this.requestRes = in.readInt();
149         this.protectionLevel = in.readInt();
150         this.tree = in.readBoolean();
151         this.parsedPermissionGroup = in.readParcelable(boot);
152         this.knownCerts = sForStringSet.unparcel(in);
153     }
154 
155     public static final Parcelable.Creator<ParsedPermission> CREATOR =
156             new Parcelable.Creator<ParsedPermission>() {
157                 @Override
158                 public ParsedPermission createFromParcel(Parcel source) {
159                     return new ParsedPermission(source);
160                 }
161 
162                 @Override
163                 public ParsedPermission[] newArray(int size) {
164                     return new ParsedPermission[size];
165                 }
166             };
167 
168     @Nullable
getBackgroundPermission()169     public String getBackgroundPermission() {
170         return backgroundPermission;
171     }
172 
173     @Nullable
getGroup()174     public String getGroup() {
175         return group;
176     }
177 
getRequestRes()178     public int getRequestRes() {
179         return requestRes;
180     }
181 
getProtectionLevel()182     public int getProtectionLevel() {
183         return protectionLevel;
184     }
185 
isTree()186     public boolean isTree() {
187         return tree;
188     }
189 
190     @Nullable
getParsedPermissionGroup()191     public ParsedPermissionGroup getParsedPermissionGroup() {
192         return parsedPermissionGroup;
193     }
194 
setProtectionLevel(int value)195     public ParsedPermission setProtectionLevel(int value) {
196         protectionLevel = value;
197         return this;
198     }
199 
setParsedPermissionGroup(@ullable ParsedPermissionGroup value)200     public ParsedPermission setParsedPermissionGroup(@Nullable ParsedPermissionGroup value) {
201         parsedPermissionGroup = value;
202         return this;
203     }
204 }
205