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 com.android.server.pm.verify.domain.models;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.UserIdInt;
22 import android.content.UriRelativeFilterGroup;
23 import android.content.pm.Signature;
24 import android.content.pm.verify.domain.DomainVerificationState;
25 import android.util.ArrayMap;
26 import android.util.SparseArray;
27 
28 import com.android.internal.util.DataClass;
29 
30 import java.util.List;
31 import java.util.Objects;
32 import java.util.UUID;
33 
34 /**
35  * State for a single package for the domain verification APIs. Stores the state of each individual
36  * domain declared by the package, including its verification state and user selection state.
37  */
38 @DataClass(genToString = true, genEqualsHashCode = true)
39 public class DomainVerificationPkgState {
40 
41     @NonNull
42     private final String mPackageName;
43 
44     @NonNull
45     private final UUID mId;
46 
47     /**
48      * Whether or not the package declares any autoVerify domains. This is separate from an empty
49      * check on the map itself, because an empty map means no response recorded, not necessarily
50      * no domains declared. When this is false, {@link #mStateMap} will be empty, but
51      * {@link #mUserStates} may contain any domains the user has explicitly chosen to
52      * allow this package to open, which may or may not be marked autoVerify.
53      */
54     private final boolean mHasAutoVerifyDomains;
55 
56     /**
57      * Map of domains to state integers. Only domains that are not set to the default value of
58      * {@link DomainVerificationState#STATE_NO_RESPONSE} are included.
59      *
60      * TODO(b/159952358): Hide the state map entirely from the caller, to allow optimizations,
61      *  such as storing no state when the package is marked as a linked app in SystemConfig.
62      */
63     @NonNull
64     private final ArrayMap<String, Integer> mStateMap;
65 
66     @NonNull
67     private final SparseArray<DomainVerificationInternalUserState> mUserStates;
68 
69     /**
70      * If previously recorded, the SHA-256 signing cert digest of the package to attach to.
71      * When doing restoration of a previously backed up state, if the signature does not
72      * match the package being scanned/installed on device, it will be rejected.
73      *
74      * It's assumed the domain verification agent will eventually re-verify this domain
75      * and revoke if necessary.
76      *
77      * @see android.util.PackageUtils#computeSignaturesSha256Digest(Signature[])
78      */
79     @Nullable
80     private final String mBackupSignatureHash;
81 
82     /**
83      * List of {@link UriRelativeFilterGroup} for filtering domains.
84      */
85     @NonNull
86     private final ArrayMap<String, List<UriRelativeFilterGroup>> mUriRelativeFilterGroupMap;
87 
DomainVerificationPkgState(@onNull String packageName, @NonNull UUID id, boolean hasAutoVerifyDomains)88     public DomainVerificationPkgState(@NonNull String packageName, @NonNull UUID id,
89             boolean hasAutoVerifyDomains) {
90         this(packageName, id, hasAutoVerifyDomains, new ArrayMap<>(0), new SparseArray<>(0), null,
91                 new ArrayMap<>());
92     }
93 
DomainVerificationPkgState(@onNull DomainVerificationPkgState pkgState, @NonNull UUID id, boolean hasAutoVerifyDomains)94     public DomainVerificationPkgState(@NonNull DomainVerificationPkgState pkgState,
95             @NonNull UUID id, boolean hasAutoVerifyDomains) {
96         this(pkgState.getPackageName(), id, hasAutoVerifyDomains, pkgState.getStateMap(),
97                 pkgState.getUserStates(), null, new ArrayMap<>());
98     }
99 
DomainVerificationPkgState(@onNull String packageName, @NonNull UUID id, boolean hasAutoVerifyDomains, @NonNull ArrayMap<String, Integer> stateMap, @NonNull SparseArray<DomainVerificationInternalUserState> userStates, @Nullable String backupSignatureHash)100     public DomainVerificationPkgState(@NonNull String packageName, @NonNull UUID id,
101             boolean hasAutoVerifyDomains, @NonNull ArrayMap<String, Integer> stateMap,
102             @NonNull SparseArray<DomainVerificationInternalUserState> userStates,
103             @Nullable String backupSignatureHash) {
104         this(packageName, id, hasAutoVerifyDomains, stateMap, userStates, backupSignatureHash,
105                 new ArrayMap<>());
106     }
107 
108     @Nullable
getUserState(@serIdInt int userId)109     public DomainVerificationInternalUserState getUserState(@UserIdInt int userId) {
110         return mUserStates.get(userId);
111     }
112 
113     @Nullable
getOrCreateUserState( @serIdInt int userId)114     public DomainVerificationInternalUserState getOrCreateUserState(
115             @UserIdInt int userId) {
116         DomainVerificationInternalUserState userState = mUserStates.get(userId);
117         if (userState == null) {
118             userState = new DomainVerificationInternalUserState(userId);
119             mUserStates.put(userId, userState);
120         }
121         return userState;
122     }
123 
removeUser(@serIdInt int userId)124     public void removeUser(@UserIdInt int userId) {
125         mUserStates.remove(userId);
126     }
127 
removeAllUsers()128     public void removeAllUsers() {
129         mUserStates.clear();
130     }
131 
userStatesHashCode()132     private int userStatesHashCode() {
133         return mUserStates.contentHashCode();
134     }
135 
userStatesEquals( @onNull SparseArray<DomainVerificationInternalUserState> other)136     private boolean userStatesEquals(
137             @NonNull SparseArray<DomainVerificationInternalUserState> other) {
138         return mUserStates.contentEquals(other);
139     }
140 
141 
142 
143     // Code below generated by codegen v1.0.23.
144     //
145     // DO NOT MODIFY!
146     // CHECKSTYLE:OFF Generated code
147     //
148     // To regenerate run:
149     // $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/core/java/com/android/server/pm/verify/domain/models/DomainVerificationPkgState.java
150     //
151     // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
152     //   Settings > Editor > Code Style > Formatter Control
153     //@formatter:off
154 
155 
156     /**
157      * Creates a new DomainVerificationPkgState.
158      *
159      * @param hasAutoVerifyDomains
160      *   Whether or not the package declares any autoVerify domains. This is separate from an empty
161      *   check on the map itself, because an empty map means no response recorded, not necessarily
162      *   no domains declared. When this is false, {@link #mStateMap} will be empty, but
163      *   {@link #mUserStates} may contain any domains the user has explicitly chosen to
164      *   allow this package to open, which may or may not be marked autoVerify.
165      * @param stateMap
166      *   Map of domains to state integers. Only domains that are not set to the default value of
167      *   {@link DomainVerificationState#STATE_NO_RESPONSE} are included.
168      *
169      *   TODO(b/159952358): Hide the state map entirely from the caller, to allow optimizations,
170      *    such as storing no state when the package is marked as a linked app in SystemConfig.
171      * @param backupSignatureHash
172      *   If previously recorded, the SHA-256 signing cert digest of the package to attach to.
173      *   When doing restoration of a previously backed up state, if the signature does not
174      *   match the package being scanned/installed on device, it will be rejected.
175      *
176      *   It's assumed the domain verification agent will eventually re-verify this domain
177      *   and revoke if necessary.
178      * @param uriRelativeFilterGroupMap
179      *   List of {@link UriRelativeFilterGroup} for filtering domains.
180      */
181     @DataClass.Generated.Member
DomainVerificationPkgState( @onNull String packageName, @NonNull UUID id, boolean hasAutoVerifyDomains, @NonNull ArrayMap<String,Integer> stateMap, @NonNull SparseArray<DomainVerificationInternalUserState> userStates, @Nullable String backupSignatureHash, @NonNull ArrayMap<String,List<UriRelativeFilterGroup>> uriRelativeFilterGroupMap)182     public DomainVerificationPkgState(
183             @NonNull String packageName,
184             @NonNull UUID id,
185             boolean hasAutoVerifyDomains,
186             @NonNull ArrayMap<String,Integer> stateMap,
187             @NonNull SparseArray<DomainVerificationInternalUserState> userStates,
188             @Nullable String backupSignatureHash,
189             @NonNull ArrayMap<String,List<UriRelativeFilterGroup>> uriRelativeFilterGroupMap) {
190         this.mPackageName = packageName;
191         com.android.internal.util.AnnotationValidations.validate(
192                 NonNull.class, null, mPackageName);
193         this.mId = id;
194         com.android.internal.util.AnnotationValidations.validate(
195                 NonNull.class, null, mId);
196         this.mHasAutoVerifyDomains = hasAutoVerifyDomains;
197         this.mStateMap = stateMap;
198         com.android.internal.util.AnnotationValidations.validate(
199                 NonNull.class, null, mStateMap);
200         this.mUserStates = userStates;
201         com.android.internal.util.AnnotationValidations.validate(
202                 NonNull.class, null, mUserStates);
203         this.mBackupSignatureHash = backupSignatureHash;
204         this.mUriRelativeFilterGroupMap = uriRelativeFilterGroupMap;
205         com.android.internal.util.AnnotationValidations.validate(
206                 NonNull.class, null, mUriRelativeFilterGroupMap);
207 
208         // onConstructed(); // You can define this method to get a callback
209     }
210 
211     @DataClass.Generated.Member
getPackageName()212     public @NonNull String getPackageName() {
213         return mPackageName;
214     }
215 
216     @DataClass.Generated.Member
getId()217     public @NonNull UUID getId() {
218         return mId;
219     }
220 
221     /**
222      * Whether or not the package declares any autoVerify domains. This is separate from an empty
223      * check on the map itself, because an empty map means no response recorded, not necessarily
224      * no domains declared. When this is false, {@link #mStateMap} will be empty, but
225      * {@link #mUserStates} may contain any domains the user has explicitly chosen to
226      * allow this package to open, which may or may not be marked autoVerify.
227      */
228     @DataClass.Generated.Member
isHasAutoVerifyDomains()229     public boolean isHasAutoVerifyDomains() {
230         return mHasAutoVerifyDomains;
231     }
232 
233     /**
234      * Map of domains to state integers. Only domains that are not set to the default value of
235      * {@link DomainVerificationState#STATE_NO_RESPONSE} are included.
236      *
237      * TODO(b/159952358): Hide the state map entirely from the caller, to allow optimizations,
238      *  such as storing no state when the package is marked as a linked app in SystemConfig.
239      */
240     @DataClass.Generated.Member
getStateMap()241     public @NonNull ArrayMap<String,Integer> getStateMap() {
242         return mStateMap;
243     }
244 
245     @DataClass.Generated.Member
getUserStates()246     public @NonNull SparseArray<DomainVerificationInternalUserState> getUserStates() {
247         return mUserStates;
248     }
249 
250     /**
251      * If previously recorded, the SHA-256 signing cert digest of the package to attach to.
252      * When doing restoration of a previously backed up state, if the signature does not
253      * match the package being scanned/installed on device, it will be rejected.
254      *
255      * It's assumed the domain verification agent will eventually re-verify this domain
256      * and revoke if necessary.
257      *
258      * @see android.util.PackageUtils#computeSignaturesSha256Digest(Signature[])
259      */
260     @DataClass.Generated.Member
getBackupSignatureHash()261     public @Nullable String getBackupSignatureHash() {
262         return mBackupSignatureHash;
263     }
264 
265     /**
266      * List of {@link UriRelativeFilterGroup} for filtering domains.
267      */
268     @DataClass.Generated.Member
getUriRelativeFilterGroupMap()269     public @NonNull ArrayMap<String,List<UriRelativeFilterGroup>> getUriRelativeFilterGroupMap() {
270         return mUriRelativeFilterGroupMap;
271     }
272 
273     @Override
274     @DataClass.Generated.Member
toString()275     public String toString() {
276         // You can override field toString logic by defining methods like:
277         // String fieldNameToString() { ... }
278 
279         return "DomainVerificationPkgState { " +
280                 "packageName = " + mPackageName + ", " +
281                 "id = " + mId + ", " +
282                 "hasAutoVerifyDomains = " + mHasAutoVerifyDomains + ", " +
283                 "stateMap = " + mStateMap + ", " +
284                 "userStates = " + mUserStates + ", " +
285                 "backupSignatureHash = " + mBackupSignatureHash + ", " +
286                 "uriRelativeFilterGroupMap = " + mUriRelativeFilterGroupMap +
287         " }";
288     }
289 
290     @Override
291     @DataClass.Generated.Member
equals(@ullable Object o)292     public boolean equals(@Nullable Object o) {
293         // You can override field equality logic by defining either of the methods like:
294         // boolean fieldNameEquals(DomainVerificationPkgState other) { ... }
295         // boolean fieldNameEquals(FieldType otherValue) { ... }
296 
297         if (this == o) return true;
298         if (o == null || getClass() != o.getClass()) return false;
299         @SuppressWarnings("unchecked")
300         DomainVerificationPkgState that = (DomainVerificationPkgState) o;
301         //noinspection PointlessBooleanExpression
302         return true
303                 && Objects.equals(mPackageName, that.mPackageName)
304                 && Objects.equals(mId, that.mId)
305                 && mHasAutoVerifyDomains == that.mHasAutoVerifyDomains
306                 && Objects.equals(mStateMap, that.mStateMap)
307                 && userStatesEquals(that.mUserStates)
308                 && Objects.equals(mBackupSignatureHash, that.mBackupSignatureHash)
309                 && Objects.equals(mUriRelativeFilterGroupMap, that.mUriRelativeFilterGroupMap);
310     }
311 
312     @Override
313     @DataClass.Generated.Member
hashCode()314     public int hashCode() {
315         // You can override field hashCode logic by defining methods like:
316         // int fieldNameHashCode() { ... }
317 
318         int _hash = 1;
319         _hash = 31 * _hash + Objects.hashCode(mPackageName);
320         _hash = 31 * _hash + Objects.hashCode(mId);
321         _hash = 31 * _hash + Boolean.hashCode(mHasAutoVerifyDomains);
322         _hash = 31 * _hash + Objects.hashCode(mStateMap);
323         _hash = 31 * _hash + userStatesHashCode();
324         _hash = 31 * _hash + Objects.hashCode(mBackupSignatureHash);
325         _hash = 31 * _hash + Objects.hashCode(mUriRelativeFilterGroupMap);
326         return _hash;
327     }
328 
329     @DataClass.Generated(
330             time = 1707351734724L,
331             codegenVersion = "1.0.23",
332             sourceFile = "frameworks/base/services/core/java/com/android/server/pm/verify/domain/models/DomainVerificationPkgState.java",
333             inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.util.UUID mId\nprivate final  boolean mHasAutoVerifyDomains\nprivate final @android.annotation.NonNull android.util.ArrayMap<java.lang.String,java.lang.Integer> mStateMap\nprivate final @android.annotation.NonNull android.util.SparseArray<com.android.server.pm.verify.domain.models.DomainVerificationInternalUserState> mUserStates\nprivate final @android.annotation.Nullable java.lang.String mBackupSignatureHash\nprivate final @android.annotation.NonNull android.util.ArrayMap<java.lang.String,java.util.List<android.content.UriRelativeFilterGroup>> mUriRelativeFilterGroupMap\npublic @android.annotation.Nullable com.android.server.pm.verify.domain.models.DomainVerificationInternalUserState getUserState(int)\npublic @android.annotation.Nullable com.android.server.pm.verify.domain.models.DomainVerificationInternalUserState getOrCreateUserState(int)\npublic  void removeUser(int)\npublic  void removeAllUsers()\nprivate  int userStatesHashCode()\nprivate  boolean userStatesEquals(android.util.SparseArray<com.android.server.pm.verify.domain.models.DomainVerificationInternalUserState>)\nclass DomainVerificationPkgState extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genToString=true, genEqualsHashCode=true)")
334     @Deprecated
__metadata()335     private void __metadata() {}
336 
337 
338     //@formatter:on
339     // End of generated code
340 
341 }
342