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