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 com.android.server.devicepolicy;
18 
19 import static android.app.admin.DevicePolicyIdentifiers.PACKAGES_SUSPENDED_POLICY;
20 import static android.app.admin.DevicePolicyIdentifiers.USER_CONTROL_DISABLED_PACKAGES_POLICY;
21 import static android.app.admin.PolicyUpdateReceiver.EXTRA_POLICY_TARGET_USER_ID;
22 import static android.app.admin.PolicyUpdateReceiver.EXTRA_POLICY_UPDATE_RESULT_KEY;
23 import static android.app.admin.PolicyUpdateResult.RESULT_FAILURE_CONFLICTING_ADMIN_POLICY;
24 import static android.app.admin.PolicyUpdateResult.RESULT_FAILURE_HARDWARE_LIMITATION;
25 import static android.app.admin.PolicyUpdateResult.RESULT_FAILURE_STORAGE_LIMIT_REACHED;
26 import static android.app.admin.PolicyUpdateResult.RESULT_POLICY_CLEARED;
27 import static android.app.admin.PolicyUpdateResult.RESULT_POLICY_SET;
28 import static android.content.pm.UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT;
29 
30 import android.Manifest;
31 import android.annotation.NonNull;
32 import android.annotation.Nullable;
33 import android.app.AppGlobals;
34 import android.app.BroadcastOptions;
35 import android.app.admin.BooleanPolicyValue;
36 import android.app.admin.DevicePolicyIdentifiers;
37 import android.app.admin.DevicePolicyManager;
38 import android.app.admin.DevicePolicyState;
39 import android.app.admin.IntentFilterPolicyKey;
40 import android.app.admin.PolicyKey;
41 import android.app.admin.PolicyUpdateReceiver;
42 import android.app.admin.PolicyValue;
43 import android.app.admin.TargetUser;
44 import android.app.admin.UserRestrictionPolicyKey;
45 import android.app.admin.flags.Flags;
46 import android.content.ComponentName;
47 import android.content.Context;
48 import android.content.Intent;
49 import android.content.IntentFilter;
50 import android.content.pm.IPackageManager;
51 import android.content.pm.PackageManager;
52 import android.content.pm.ResolveInfo;
53 import android.content.pm.UserInfo;
54 import android.content.pm.UserProperties;
55 import android.os.Binder;
56 import android.os.Bundle;
57 import android.os.Environment;
58 import android.os.Parcel;
59 import android.os.RemoteException;
60 import android.os.UserHandle;
61 import android.os.UserManager;
62 import android.telephony.TelephonyManager;
63 import android.util.AtomicFile;
64 import android.util.IndentingPrintWriter;
65 import android.util.Log;
66 import android.util.SparseArray;
67 import android.util.Xml;
68 
69 import com.android.internal.util.XmlUtils;
70 import com.android.modules.utils.TypedXmlPullParser;
71 import com.android.modules.utils.TypedXmlSerializer;
72 import com.android.server.utils.Slogf;
73 
74 import libcore.io.IoUtils;
75 
76 import org.xmlpull.v1.XmlPullParserException;
77 
78 import java.io.File;
79 import java.io.FileOutputStream;
80 import java.io.IOException;
81 import java.io.InputStream;
82 import java.nio.file.Files;
83 import java.nio.file.Path;
84 import java.nio.file.StandardCopyOption;
85 import java.util.ArrayList;
86 import java.util.Collections;
87 import java.util.HashMap;
88 import java.util.HashSet;
89 import java.util.LinkedHashMap;
90 import java.util.List;
91 import java.util.Map;
92 import java.util.Objects;
93 import java.util.Set;
94 
95 /**
96  * Class responsible for setting, resolving, and enforcing policies set by multiple management
97  * admins on the device.
98  */
99 final class DevicePolicyEngine {
100     static final String TAG = "DevicePolicyEngine";
101 
102     // TODO(b/281701062): reference role name from role manager once its exposed.
103     static final String DEVICE_LOCK_CONTROLLER_ROLE =
104             "android.app.role.SYSTEM_FINANCED_DEVICE_CONTROLLER";
105 
106     private static final String CELLULAR_2G_USER_RESTRICTION_ID =
107             DevicePolicyIdentifiers.getIdentifierForUserRestriction(
108                     UserManager.DISALLOW_CELLULAR_2G);
109 
110     //TODO(b/295504706) : Speak to security team to decide what to set Policy_Size_Limit
111     static final int DEFAULT_POLICY_SIZE_LIMIT = -1;
112 
113     private final Context mContext;
114     private final UserManager mUserManager;
115 
116     // TODO(b/256849338): add more granular locks
117     private final Object mLock;
118 
119     /**
120      * Map of <userId, Map<policyKey, policyState>>
121      */
122     private final SparseArray<Map<PolicyKey, PolicyState<?>>> mLocalPolicies;
123 
124     /**
125      * Map of <policyKey, policyState>
126      */
127     private final Map<PolicyKey, PolicyState<?>> mGlobalPolicies;
128 
129     /**
130      * Map containing the current set of admins in each user with active policies.
131      */
132     private final SparseArray<Set<EnforcingAdmin>> mEnforcingAdmins;
133 
134     private final SparseArray<HashMap<EnforcingAdmin, Integer>> mAdminPolicySize;
135 
136     private int mPolicySizeLimit = DEFAULT_POLICY_SIZE_LIMIT;
137 
138     private final DeviceAdminServiceController mDeviceAdminServiceController;
139 
DevicePolicyEngine( @onNull Context context, @NonNull DeviceAdminServiceController deviceAdminServiceController, @NonNull Object lock)140     DevicePolicyEngine(
141             @NonNull Context context,
142             @NonNull DeviceAdminServiceController deviceAdminServiceController,
143             @NonNull Object lock) {
144         mContext = Objects.requireNonNull(context);
145         mDeviceAdminServiceController = Objects.requireNonNull(deviceAdminServiceController);
146         mLock = Objects.requireNonNull(lock);
147         mUserManager = mContext.getSystemService(UserManager.class);
148         mLocalPolicies = new SparseArray<>();
149         mGlobalPolicies = new HashMap<>();
150         mEnforcingAdmins = new SparseArray<>();
151         mAdminPolicySize = new SparseArray<>();
152     }
153 
maybeForceEnforcementRefreshLocked(@onNull PolicyDefinition<?> policyDefinition)154     private void maybeForceEnforcementRefreshLocked(@NonNull PolicyDefinition<?> policyDefinition) {
155         try {
156             if (shouldForceEnforcementRefresh(policyDefinition)) {
157                 // This is okay because it's only true for user restrictions which are all <Boolean>
158                 forceEnforcementRefreshLocked((PolicyDefinition<Boolean>) policyDefinition);
159             }
160         } catch (Throwable e) {
161             // Catch any possible exceptions just to be on the safe side
162             Log.e(TAG, "Exception throw during maybeForceEnforcementRefreshLocked", e);
163         }
164     }
165 
shouldForceEnforcementRefresh(@onNull PolicyDefinition<?> policyDefinition)166     private boolean shouldForceEnforcementRefresh(@NonNull PolicyDefinition<?> policyDefinition) {
167         // These are all "not nullable" but for the purposes of maximum safety for a lightly tested
168         // change we check here
169         if (policyDefinition == null) {
170             return false;
171         }
172         PolicyKey policyKey = policyDefinition.getPolicyKey();
173         if (policyKey == null) {
174             return false;
175         }
176 
177         if (policyKey instanceof UserRestrictionPolicyKey) {
178             // b/307481299 We must force all user restrictions to re-sync local
179             // + global on each set/clear
180             return true;
181         }
182 
183         return false;
184     }
185 
forceEnforcementRefreshLocked(PolicyDefinition<Boolean> policyDefinition)186     private void forceEnforcementRefreshLocked(PolicyDefinition<Boolean> policyDefinition) {
187         Binder.withCleanCallingIdentity(() -> {
188             // Sync global state
189             PolicyValue<Boolean> globalValue = new BooleanPolicyValue(false);
190             try {
191                 PolicyState<Boolean> policyState = getGlobalPolicyStateLocked(policyDefinition);
192                 globalValue = policyState.getCurrentResolvedPolicy();
193             } catch (IllegalArgumentException e) {
194                 // Expected for local-only policies
195             }
196 
197             enforcePolicy(policyDefinition, globalValue, UserHandle.USER_ALL);
198 
199             // Loop through each user and sync that user's state
200             for (UserInfo user : mUserManager.getUsers()) {
201                 PolicyValue<Boolean> localValue = new BooleanPolicyValue(false);
202                 try {
203                     PolicyState<Boolean> localPolicyState = getLocalPolicyStateLocked(
204                             policyDefinition, user.id);
205                     localValue = localPolicyState.getCurrentResolvedPolicy();
206                 } catch (IllegalArgumentException e) {
207                     // Expected for global-only policies
208                 }
209 
210                 enforcePolicy(policyDefinition, localValue, user.id);
211             }
212         });
213     }
214 
215     /**
216      * Set the policy for the provided {@code policyDefinition} (see {@link PolicyDefinition}) and
217      * {@code enforcingAdmin} to the provided {@code value}.
218      *
219      * <p>If {@code skipEnforcePolicy} is true, it sets the policies in the internal data structure
220      * but doesn't call the enforcing logic.
221      */
setLocalPolicy( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, @NonNull PolicyValue<V> value, int userId, boolean skipEnforcePolicy)222     <V> void setLocalPolicy(
223             @NonNull PolicyDefinition<V> policyDefinition,
224             @NonNull EnforcingAdmin enforcingAdmin,
225             @NonNull PolicyValue<V> value,
226             int userId,
227             boolean skipEnforcePolicy) {
228         Objects.requireNonNull(policyDefinition);
229         Objects.requireNonNull(enforcingAdmin);
230 
231         synchronized (mLock) {
232             PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId);
233             if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
234                 if (!handleAdminPolicySizeLimit(localPolicyState, enforcingAdmin, value,
235                         policyDefinition, userId)) {
236                     return;
237                 }
238             }
239 
240             if (policyDefinition.isNonCoexistablePolicy()) {
241                 setNonCoexistableLocalPolicyLocked(policyDefinition, localPolicyState,
242                         enforcingAdmin, value, userId, skipEnforcePolicy);
243                 return;
244             }
245 
246             boolean hasGlobalPolicies = hasGlobalPolicyLocked(policyDefinition);
247             boolean policyChanged;
248             if (hasGlobalPolicies) {
249                 PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition);
250                 policyChanged = localPolicyState.addPolicy(
251                         enforcingAdmin,
252                         value,
253                         globalPolicyState.getPoliciesSetByAdmins());
254             } else {
255                 policyChanged = localPolicyState.addPolicy(enforcingAdmin, value);
256             }
257 
258             // No need to notify admins as no new policy is actually enforced, we're just filling in
259             // the data structures.
260             if (!skipEnforcePolicy) {
261                 maybeForceEnforcementRefreshLocked(policyDefinition);
262                 if (policyChanged) {
263                     onLocalPolicyChangedLocked(policyDefinition, enforcingAdmin, userId);
264                 }
265                 boolean policyEnforced = Objects.equals(
266                         localPolicyState.getCurrentResolvedPolicy(), value);
267                 // TODO(b/285532044): remove hack and handle properly
268                 if (!policyEnforced && shouldApplyPackageSetUnionPolicyHack(policyDefinition)) {
269                     PolicyValue<Set<String>> parsedValue = (PolicyValue<Set<String>>) value;
270                     PolicyValue<Set<String>> parsedResolvedValue =
271                             (PolicyValue<Set<String>>) localPolicyState.getCurrentResolvedPolicy();
272                     policyEnforced = (parsedResolvedValue != null && parsedValue != null
273                             && parsedResolvedValue.getValue().containsAll(parsedValue.getValue()));
274                 }
275                 sendPolicyResultToAdmin(
276                         enforcingAdmin,
277                         policyDefinition,
278                         // TODO: we're always sending this for now, should properly handle errors.
279                         policyEnforced
280                                 ? RESULT_POLICY_SET : RESULT_FAILURE_CONFLICTING_ADMIN_POLICY,
281                         userId);
282             }
283 
284             updateDeviceAdminServiceOnPolicyAddLocked(enforcingAdmin);
285 
286             write();
287 
288             applyToInheritableProfiles(policyDefinition, enforcingAdmin, value, userId);
289         }
290     }
291 
292     /**
293      * Sets a non-coexistable policy, meaning it doesn't get resolved against other policies set
294      * by other admins, and no callbacks are sent to admins, this is just storing and
295      * enforcing the policy.
296      *
297      * <p>Passing a {@code null} value means the policy set by this admin should be removed.
298      */
setNonCoexistableLocalPolicyLocked( PolicyDefinition<V> policyDefinition, PolicyState<V> localPolicyState, EnforcingAdmin enforcingAdmin, @Nullable PolicyValue<V> value, int userId, boolean skipEnforcePolicy)299     private <V> void setNonCoexistableLocalPolicyLocked(
300             PolicyDefinition<V> policyDefinition,
301             PolicyState<V> localPolicyState,
302             EnforcingAdmin enforcingAdmin,
303             @Nullable PolicyValue<V> value,
304             int userId,
305             boolean skipEnforcePolicy) {
306         if (value == null) {
307             localPolicyState.removePolicy(enforcingAdmin);
308         } else {
309             localPolicyState.addPolicy(enforcingAdmin, value);
310         }
311         if (!skipEnforcePolicy) {
312             enforcePolicy(policyDefinition, value, userId);
313         }
314         if (localPolicyState.getPoliciesSetByAdmins().isEmpty()) {
315             removeLocalPolicyStateLocked(policyDefinition, userId);
316         }
317         updateDeviceAdminServiceOnPolicyAddLocked(enforcingAdmin);
318         write();
319         applyToInheritableProfiles(policyDefinition, enforcingAdmin, value, userId);
320     }
321 
322     // TODO: add more documentation on broadcasts/callbacks to use to get current enforced values
323 
324     /**
325      * Set the policy for the provided {@code policyDefinition}
326      * (see {@link PolicyDefinition}) and {@code enforcingAdmin} to the provided {@code value}.
327      */
setLocalPolicy( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, @NonNull PolicyValue<V> value, int userId)328     <V> void setLocalPolicy(
329             @NonNull PolicyDefinition<V> policyDefinition,
330             @NonNull EnforcingAdmin enforcingAdmin,
331             @NonNull PolicyValue<V> value,
332             int userId) {
333         setLocalPolicy(
334                 policyDefinition, enforcingAdmin, value, userId, /* skipEnforcePolicy= */ false);
335     }
336 
337     // TODO: add more documentation on broadcasts/callbacks to use to get current enforced values
338 
339     /**
340      * Removes any previously set policy for the provided {@code policyDefinition}
341      * (see {@link PolicyDefinition}) and {@code enforcingAdmin}.
342      */
removeLocalPolicy( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, int userId)343     <V> void removeLocalPolicy(
344             @NonNull PolicyDefinition<V> policyDefinition,
345             @NonNull EnforcingAdmin enforcingAdmin,
346             int userId) {
347         Objects.requireNonNull(policyDefinition);
348         Objects.requireNonNull(enforcingAdmin);
349 
350         synchronized (mLock) {
351             maybeForceEnforcementRefreshLocked(policyDefinition);
352             if (!hasLocalPolicyLocked(policyDefinition, userId)) {
353                 return;
354             }
355             PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId);
356 
357             if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
358                 decreasePolicySizeForAdmin(localPolicyState, enforcingAdmin);
359             }
360 
361             if (policyDefinition.isNonCoexistablePolicy()) {
362                 setNonCoexistableLocalPolicyLocked(policyDefinition, localPolicyState,
363                         enforcingAdmin, /* value= */ null, userId, /* skipEnforcePolicy= */ false);
364                 return;
365             }
366 
367             boolean policyChanged;
368             if (hasGlobalPolicyLocked(policyDefinition)) {
369                 PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition);
370                 policyChanged = localPolicyState.removePolicy(
371                         enforcingAdmin,
372                         globalPolicyState.getPoliciesSetByAdmins());
373             } else {
374                 policyChanged = localPolicyState.removePolicy(enforcingAdmin);
375             }
376 
377             if (policyChanged) {
378                 onLocalPolicyChangedLocked(policyDefinition, enforcingAdmin, userId);
379             }
380 
381             // For a removePolicy to be enforced, it means no current policy exists
382             sendPolicyResultToAdmin(
383                     enforcingAdmin,
384                     policyDefinition,
385                     // TODO: we're always sending this for now, should properly handle errors.
386                     RESULT_POLICY_CLEARED,
387                     userId);
388 
389             if (localPolicyState.getPoliciesSetByAdmins().isEmpty()) {
390                 removeLocalPolicyStateLocked(policyDefinition, userId);
391             }
392 
393             updateDeviceAdminServiceOnPolicyRemoveLocked(enforcingAdmin);
394 
395             write();
396 
397             applyToInheritableProfiles(policyDefinition, enforcingAdmin, /*value */ null, userId);
398         }
399     }
400 
401     /**
402      * If any of child user has property {@link UserProperties#INHERIT_DEVICE_POLICY_FROM_PARENT}
403      * set then propagate the policy to it if value is not null
404      * else remove the policy from child.
405      */
applyToInheritableProfiles(PolicyDefinition<V> policyDefinition, EnforcingAdmin enforcingAdmin, @Nullable PolicyValue<V> value, int userId)406     private <V> void applyToInheritableProfiles(PolicyDefinition<V> policyDefinition,
407             EnforcingAdmin enforcingAdmin, @Nullable PolicyValue<V> value, int userId) {
408         if (policyDefinition.isInheritable()) {
409             Binder.withCleanCallingIdentity(() -> {
410                 List<UserInfo> userInfos = mUserManager.getProfiles(userId);
411                 for (UserInfo childUserInfo : userInfos) {
412                     int childUserId = childUserInfo.getUserHandle().getIdentifier();
413                     if (isProfileOfUser(childUserId, userId)
414                             && isInheritDevicePolicyFromParent(childUserInfo)) {
415                         if (value != null) {
416                             setLocalPolicy(policyDefinition, enforcingAdmin, value, childUserId);
417                         } else {
418                             removeLocalPolicy(policyDefinition, enforcingAdmin, childUserId);
419                         }
420                     }
421                 }
422             });
423         }
424     }
425 
426     /**
427      * Checks if given parentUserId is direct parent of childUserId.
428      */
isProfileOfUser(int childUserId, int parentUserId)429     private boolean isProfileOfUser(int childUserId, int parentUserId) {
430         UserInfo parentInfo = mUserManager.getProfileParent(childUserId);
431         return childUserId != parentUserId && parentInfo != null
432                 && parentInfo.getUserHandle().getIdentifier() == parentUserId;
433     }
434 
isInheritDevicePolicyFromParent(UserInfo userInfo)435     private boolean isInheritDevicePolicyFromParent(UserInfo userInfo) {
436         UserProperties userProperties = mUserManager.getUserProperties(userInfo.getUserHandle());
437         return userProperties != null && mUserManager.getUserProperties(userInfo.getUserHandle())
438                 .getInheritDevicePolicy() == INHERIT_DEVICE_POLICY_FROM_PARENT;
439     }
440 
441     /**
442      * Enforces the new policy and notifies relevant admins.
443      */
onLocalPolicyChangedLocked( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, int userId)444     private <V> void onLocalPolicyChangedLocked(
445             @NonNull PolicyDefinition<V> policyDefinition,
446             @NonNull EnforcingAdmin enforcingAdmin,
447             int userId) {
448 
449         PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId);
450         enforcePolicy(
451                 policyDefinition, localPolicyState.getCurrentResolvedPolicy(), userId);
452 
453         // Send policy updates to admins who've set it locally
454         sendPolicyChangedToAdminsLocked(
455                 localPolicyState,
456                 enforcingAdmin,
457                 policyDefinition,
458                 // This policy change is only relevant to a single user, not the global
459                 // policy value,
460                 userId);
461 
462         // Send policy updates to admins who've set it globally
463         if (hasGlobalPolicyLocked(policyDefinition)) {
464             PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition);
465             sendPolicyChangedToAdminsLocked(
466                     globalPolicyState,
467                     enforcingAdmin,
468                     policyDefinition,
469                     userId);
470         }
471         sendDevicePolicyChangedToSystem(userId);
472     }
473 
474     /**
475      * Set the policy for the provided {@code policyDefinition}
476      * (see {@link PolicyDefinition}) and {@code enforcingAdmin} to the provided {@code value}.
477      */
setGlobalPolicy( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, @NonNull PolicyValue<V> value)478     <V> void setGlobalPolicy(
479             @NonNull PolicyDefinition<V> policyDefinition,
480             @NonNull EnforcingAdmin enforcingAdmin,
481             @NonNull PolicyValue<V> value) {
482         setGlobalPolicy(policyDefinition, enforcingAdmin, value, /* skipEnforcePolicy= */ false);
483     }
484 
485     // TODO: add more documentation on broadcasts/callbacks to use to get current enforced values
486 
487     /**
488      * Set the policy for the provided {@code policyDefinition}
489      * (see {@link PolicyDefinition}) and {@code enforcingAdmin} to the provided {@code value}.
490      */
setGlobalPolicy( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, @NonNull PolicyValue<V> value, boolean skipEnforcePolicy)491     <V> void setGlobalPolicy(
492             @NonNull PolicyDefinition<V> policyDefinition,
493             @NonNull EnforcingAdmin enforcingAdmin,
494             @NonNull PolicyValue<V> value,
495             boolean skipEnforcePolicy) {
496 
497         Objects.requireNonNull(policyDefinition);
498         Objects.requireNonNull(enforcingAdmin);
499         Objects.requireNonNull(value);
500 
501         synchronized (mLock) {
502             PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition);
503             if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
504                 if (!handleAdminPolicySizeLimit(globalPolicyState, enforcingAdmin, value,
505                         policyDefinition, UserHandle.USER_ALL)) {
506                     return;
507                 }
508             }
509             // TODO(b/270999567): Move error handling for DISALLOW_CELLULAR_2G into the code
510             //  that honors the restriction once there's an API available
511             if (checkFor2gFailure(policyDefinition, enforcingAdmin)) {
512                 Log.i(TAG,
513                         "Device does not support capabilities required to disable 2g. Not setting"
514                                 + " global policy state.");
515                 return;
516             }
517 
518             boolean policyChanged = globalPolicyState.addPolicy(enforcingAdmin, value);
519             boolean policyAppliedOnAllUsers = applyGlobalPolicyOnUsersWithLocalPoliciesLocked(
520                     policyDefinition, enforcingAdmin, value, skipEnforcePolicy);
521 
522             // No need to notify admins as no new policy is actually enforced, we're just filling in
523             // the data structures.
524             if (!skipEnforcePolicy) {
525                 maybeForceEnforcementRefreshLocked(policyDefinition);
526                 if (policyChanged) {
527                     onGlobalPolicyChangedLocked(policyDefinition, enforcingAdmin);
528                 }
529 
530                 boolean policyAppliedGlobally = Objects.equals(
531                         globalPolicyState.getCurrentResolvedPolicy(), value);
532                 // TODO(b/285532044): remove hack and handle properly
533                 if (!policyAppliedGlobally
534                         && shouldApplyPackageSetUnionPolicyHack(policyDefinition)) {
535                     PolicyValue<Set<String>> parsedValue = (PolicyValue<Set<String>>) value;
536                     PolicyValue<Set<String>> parsedResolvedValue =
537                             (PolicyValue<Set<String>>) globalPolicyState.getCurrentResolvedPolicy();
538                     policyAppliedGlobally = (parsedResolvedValue != null && parsedValue != null
539                             && parsedResolvedValue.getValue().containsAll(parsedValue.getValue()));
540                 }
541 
542                 boolean policyApplied = policyAppliedGlobally && policyAppliedOnAllUsers;
543 
544                 sendPolicyResultToAdmin(
545                         enforcingAdmin,
546                         policyDefinition,
547                         // TODO: we're always sending this for now, should properly handle errors.
548                         policyApplied ? RESULT_POLICY_SET : RESULT_FAILURE_CONFLICTING_ADMIN_POLICY,
549                         UserHandle.USER_ALL);
550             }
551 
552             updateDeviceAdminServiceOnPolicyAddLocked(enforcingAdmin);
553 
554             write();
555         }
556     }
557 
558     // TODO: add more documentation on broadcasts/callbacks to use to get current enforced values
559 
560     /**
561      * Removes any previously set policy for the provided {@code policyDefinition}
562      * (see {@link PolicyDefinition}) and {@code enforcingAdmin}.
563      */
removeGlobalPolicy( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin)564     <V> void removeGlobalPolicy(
565             @NonNull PolicyDefinition<V> policyDefinition,
566             @NonNull EnforcingAdmin enforcingAdmin) {
567 
568         Objects.requireNonNull(policyDefinition);
569         Objects.requireNonNull(enforcingAdmin);
570 
571         synchronized (mLock) {
572             PolicyState<V> policyState = getGlobalPolicyStateLocked(policyDefinition);
573 
574             if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
575                 decreasePolicySizeForAdmin(policyState, enforcingAdmin);
576             }
577 
578             boolean policyChanged = policyState.removePolicy(enforcingAdmin);
579 
580             maybeForceEnforcementRefreshLocked(policyDefinition);
581             if (policyChanged) {
582                 onGlobalPolicyChangedLocked(policyDefinition, enforcingAdmin);
583             }
584 
585             applyGlobalPolicyOnUsersWithLocalPoliciesLocked(policyDefinition, enforcingAdmin,
586                     /* value= */ null, /* skipEnforcePolicy= */ false);
587 
588             sendPolicyResultToAdmin(
589                     enforcingAdmin,
590                     policyDefinition,
591                     // TODO: we're always sending this for now, should properly handle errors.
592                     RESULT_POLICY_CLEARED,
593                     UserHandle.USER_ALL);
594 
595             if (policyState.getPoliciesSetByAdmins().isEmpty()) {
596                 removeGlobalPolicyStateLocked(policyDefinition);
597             }
598 
599             updateDeviceAdminServiceOnPolicyRemoveLocked(enforcingAdmin);
600 
601             write();
602         }
603     }
604 
605     /**
606      * Enforces the new policy globally and notifies relevant admins.
607      */
onGlobalPolicyChangedLocked( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin)608     private <V> void onGlobalPolicyChangedLocked(
609             @NonNull PolicyDefinition<V> policyDefinition,
610             @NonNull EnforcingAdmin enforcingAdmin) {
611         PolicyState<V> policyState = getGlobalPolicyStateLocked(policyDefinition);
612 
613         enforcePolicy(policyDefinition, policyState.getCurrentResolvedPolicy(),
614                 UserHandle.USER_ALL);
615 
616         sendPolicyChangedToAdminsLocked(
617                 policyState,
618                 enforcingAdmin,
619                 policyDefinition,
620                 UserHandle.USER_ALL);
621 
622         sendDevicePolicyChangedToSystem(UserHandle.USER_ALL);
623     }
624 
625     /**
626      * Tries to enforce the global policy locally on all users that have the same policy set
627      * locally, this is only applicable to policies that can be set locally or globally
628      * (e.g. setCameraDisabled, setScreenCaptureDisabled) rather than
629      * policies that are global by nature (e.g. setting Wifi enabled/disabled).
630      *
631      * <p> A {@code null} policy value means the policy was removed
632      *
633      * <p>Returns {@code true} if the policy is enforced successfully on all users.
634      */
applyGlobalPolicyOnUsersWithLocalPoliciesLocked( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, @Nullable PolicyValue<V> value, boolean skipEnforcePolicy)635     private <V> boolean applyGlobalPolicyOnUsersWithLocalPoliciesLocked(
636             @NonNull PolicyDefinition<V> policyDefinition,
637             @NonNull EnforcingAdmin enforcingAdmin,
638             @Nullable PolicyValue<V> value,
639             boolean skipEnforcePolicy) {
640         // Global only policies can't be applied locally, return early.
641         if (policyDefinition.isGlobalOnlyPolicy()) {
642             return true;
643         }
644         boolean isAdminPolicyApplied = true;
645         for (int i = 0; i < mLocalPolicies.size(); i++) {
646             int userId = mLocalPolicies.keyAt(i);
647             if (!hasLocalPolicyLocked(policyDefinition, userId)) {
648                 continue;
649             }
650 
651             PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId);
652             PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition);
653 
654             boolean policyChanged = localPolicyState.resolvePolicy(
655                     globalPolicyState.getPoliciesSetByAdmins());
656             if (policyChanged && !skipEnforcePolicy) {
657                 enforcePolicy(
658                         policyDefinition,
659                         localPolicyState.getCurrentResolvedPolicy(),
660                         userId);
661                 sendPolicyChangedToAdminsLocked(
662                         localPolicyState,
663                         enforcingAdmin,
664                         policyDefinition,
665                         // Even though this is caused by a global policy change, admins who've set
666                         // it locally should only care about the local user state.
667                         userId);
668 
669             }
670             // TODO(b/285532044): remove hack and handle properly
671             if (shouldApplyPackageSetUnionPolicyHack(policyDefinition)) {
672                 if (!Objects.equals(value, localPolicyState.getCurrentResolvedPolicy())) {
673                     PolicyValue<Set<String>> parsedValue = (PolicyValue<Set<String>>) value;
674                     PolicyValue<Set<String>> parsedResolvedValue =
675                             (PolicyValue<Set<String>>) localPolicyState.getCurrentResolvedPolicy();
676                     isAdminPolicyApplied &= (parsedResolvedValue != null && parsedValue != null
677                             && parsedResolvedValue.getValue().containsAll(parsedValue.getValue()));
678                 }
679             } else {
680                 isAdminPolicyApplied &= Objects.equals(
681                         value, localPolicyState.getCurrentResolvedPolicy());
682             }
683         }
684         return isAdminPolicyApplied;
685     }
686 
687     /**
688      * Retrieves the resolved policy for the provided {@code policyDefinition} and {@code userId}.
689      */
690     @Nullable
getResolvedPolicy(@onNull PolicyDefinition<V> policyDefinition, int userId)691     <V> V getResolvedPolicy(@NonNull PolicyDefinition<V> policyDefinition, int userId) {
692         PolicyValue<V> resolvedValue = getResolvedPolicyValue(policyDefinition, userId);
693         return resolvedValue == null ? null : resolvedValue.getValue();
694     }
695 
getResolvedPolicyValue(@onNull PolicyDefinition<V> policyDefinition, int userId)696     private <V> PolicyValue<V> getResolvedPolicyValue(@NonNull PolicyDefinition<V> policyDefinition,
697             int userId) {
698         Objects.requireNonNull(policyDefinition);
699 
700         synchronized (mLock) {
701             PolicyValue<V> resolvedValue = null;
702             if (hasLocalPolicyLocked(policyDefinition, userId)) {
703                 resolvedValue = getLocalPolicyStateLocked(
704                         policyDefinition, userId).getCurrentResolvedPolicy();
705             } else if (hasGlobalPolicyLocked(policyDefinition)) {
706                 resolvedValue = getGlobalPolicyStateLocked(
707                         policyDefinition).getCurrentResolvedPolicy();
708             }
709             return resolvedValue;
710         }
711     }
712 
713     /**
714      * Retrieves resolved policy for the provided {@code policyDefinition} and a list of
715      * users.
716      */
717     @Nullable
getResolvedPolicyAcrossUsers(@onNull PolicyDefinition<V> policyDefinition, List<Integer> users)718     <V> V getResolvedPolicyAcrossUsers(@NonNull PolicyDefinition<V> policyDefinition,
719             List<Integer> users) {
720         Objects.requireNonNull(policyDefinition);
721 
722         List<PolicyValue<V>> adminPolicies = new ArrayList<>();
723         synchronized (mLock) {
724             for (int userId : users) {
725                 PolicyValue<V> resolvedValue = getResolvedPolicyValue(policyDefinition, userId);
726                 if (resolvedValue != null) {
727                     adminPolicies.add(resolvedValue);
728                 }
729             }
730         }
731         // We will be aggregating PolicyValue across multiple admins across multiple users,
732         // including different policies set by the same admin on different users. This is
733         // not supported by ResolutionMechanism generically, instead we need to call the special
734         // resolve() method that doesn't care about admins who set the policy. Note that not every
735         // ResolutionMechanism supports this.
736         PolicyValue<V> resolvedValue =
737                 policyDefinition.getResolutionMechanism().resolve(adminPolicies);
738         return resolvedValue == null ? null : resolvedValue.getValue();
739     }
740 
741     /**
742      * Retrieves the policy set by the admin for the provided {@code policyDefinition} and
743      * {@code userId} if one was set, otherwise returns {@code null}.
744      */
745     @Nullable
getLocalPolicySetByAdmin( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, int userId)746     <V> V getLocalPolicySetByAdmin(
747             @NonNull PolicyDefinition<V> policyDefinition,
748             @NonNull EnforcingAdmin enforcingAdmin,
749             int userId) {
750         Objects.requireNonNull(policyDefinition);
751         Objects.requireNonNull(enforcingAdmin);
752 
753         synchronized (mLock) {
754             if (!hasLocalPolicyLocked(policyDefinition, userId)) {
755                 return null;
756             }
757             PolicyValue<V> value = getLocalPolicyStateLocked(policyDefinition, userId)
758                     .getPoliciesSetByAdmins().get(enforcingAdmin);
759             return value == null ? null : value.getValue();
760         }
761     }
762 
763     /**
764      * Retrieves the global policy set by the admin for the provided {@code policyDefinition}
765      * if one was set, otherwise returns {@code null}.
766      */
767     @Nullable
getGlobalPolicySetByAdmin( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin)768     <V> V getGlobalPolicySetByAdmin(
769             @NonNull PolicyDefinition<V> policyDefinition,
770             @NonNull EnforcingAdmin enforcingAdmin) {
771         Objects.requireNonNull(policyDefinition);
772         Objects.requireNonNull(enforcingAdmin);
773 
774         synchronized (mLock) {
775             if (!hasGlobalPolicyLocked(policyDefinition)) {
776                 return null;
777             }
778             PolicyValue<V> value = getGlobalPolicyStateLocked(policyDefinition)
779                     .getPoliciesSetByAdmins().get(enforcingAdmin);
780             return value == null ? null : value.getValue();
781         }
782     }
783 
784     /**
785      * Retrieves the values set for the provided {@code policyDefinition} by each admin.
786      */
787     @NonNull
getLocalPoliciesSetByAdmins( @onNull PolicyDefinition<V> policyDefinition, int userId)788     <V> LinkedHashMap<EnforcingAdmin, PolicyValue<V>> getLocalPoliciesSetByAdmins(
789             @NonNull PolicyDefinition<V> policyDefinition,
790             int userId) {
791         Objects.requireNonNull(policyDefinition);
792 
793         synchronized (mLock) {
794             if (!hasLocalPolicyLocked(policyDefinition, userId)) {
795                 return new LinkedHashMap<>();
796             }
797             return getLocalPolicyStateLocked(policyDefinition, userId).getPoliciesSetByAdmins();
798         }
799     }
800 
801     /**
802      * Retrieves the values set for the provided {@code policyDefinition} by each admin.
803      */
804     @NonNull
getGlobalPoliciesSetByAdmins( @onNull PolicyDefinition<V> policyDefinition)805     <V> LinkedHashMap<EnforcingAdmin, PolicyValue<V>> getGlobalPoliciesSetByAdmins(
806             @NonNull PolicyDefinition<V> policyDefinition) {
807         Objects.requireNonNull(policyDefinition);
808 
809         synchronized (mLock) {
810             if (!hasGlobalPolicyLocked(policyDefinition)) {
811                 return new LinkedHashMap<>();
812             }
813             return getGlobalPolicyStateLocked(policyDefinition).getPoliciesSetByAdmins();
814         }
815     }
816 
817     /**
818      * Returns the policies set by the given admin that share the same
819      * {@link PolicyKey#getIdentifier()} as the provided {@code policyDefinition}.
820      *
821      * <p>For example, getLocalPolicyKeysSetByAdmin(PERMISSION_GRANT, admin) returns all permission
822      * grants set by the given admin.
823      *
824      * <p>Note that this will always return at most one item for policies that do not require
825      * additional params (e.g. {@link PolicyDefinition#LOCK_TASK} vs
826      * {@link PolicyDefinition#PERMISSION_GRANT(String, String)}).
827      */
828     @NonNull
getLocalPolicyKeysSetByAdmin( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, int userId)829     <V> Set<PolicyKey> getLocalPolicyKeysSetByAdmin(
830             @NonNull PolicyDefinition<V> policyDefinition,
831             @NonNull EnforcingAdmin enforcingAdmin,
832             int userId) {
833         Objects.requireNonNull(policyDefinition);
834         Objects.requireNonNull(enforcingAdmin);
835 
836         synchronized (mLock) {
837             if (policyDefinition.isGlobalOnlyPolicy() || !mLocalPolicies.contains(userId)) {
838                 return Set.of();
839             }
840             Set<PolicyKey> keys = new HashSet<>();
841             for (PolicyKey key : mLocalPolicies.get(userId).keySet()) {
842                 if (key.hasSameIdentifierAs(policyDefinition.getPolicyKey())
843                         && mLocalPolicies.get(userId).get(key).getPoliciesSetByAdmins()
844                         .containsKey(enforcingAdmin)) {
845                     keys.add(key);
846                 }
847             }
848             return keys;
849         }
850     }
851 
852     /**
853      * Returns all the {@code policyKeys} set by any admin that share the same
854      * {@link PolicyKey#getIdentifier()} as the provided {@code policyDefinition}.
855      *
856      * <p>For example, getLocalPolicyKeysSetByAllAdmins(PERMISSION_GRANT) returns all permission
857      * grants set by any admin.
858      *
859      * <p>Note that this will always return at most one item for policies that do not require
860      * additional params (e.g. {@link PolicyDefinition#LOCK_TASK} vs
861      * {@link PolicyDefinition#PERMISSION_GRANT(String, String)}).
862      */
863     @NonNull
getLocalPolicyKeysSetByAllAdmins( @onNull PolicyDefinition<V> policyDefinition, int userId)864     <V> Set<PolicyKey> getLocalPolicyKeysSetByAllAdmins(
865             @NonNull PolicyDefinition<V> policyDefinition,
866             int userId) {
867         Objects.requireNonNull(policyDefinition);
868 
869         synchronized (mLock) {
870             if (policyDefinition.isGlobalOnlyPolicy() || !mLocalPolicies.contains(userId)) {
871                 return Set.of();
872             }
873             Set<PolicyKey> keys = new HashSet<>();
874             for (PolicyKey key : mLocalPolicies.get(userId).keySet()) {
875                 if (key.hasSameIdentifierAs(policyDefinition.getPolicyKey())) {
876                     keys.add(key);
877                 }
878             }
879             return keys;
880         }
881     }
882 
883     /**
884      * Returns all user restriction policies set by the given admin.
885      *
886      * <p>Pass in {@link UserHandle#USER_ALL} for {@code userId} to get global restrictions set by
887      * the admin
888      */
889     @NonNull
getUserRestrictionPolicyKeysForAdmin( @onNull EnforcingAdmin admin, int userId)890     Set<UserRestrictionPolicyKey> getUserRestrictionPolicyKeysForAdmin(
891             @NonNull EnforcingAdmin admin,
892             int userId) {
893         Objects.requireNonNull(admin);
894         synchronized (mLock) {
895             if (userId == UserHandle.USER_ALL) {
896                 return getUserRestrictionPolicyKeysForAdminLocked(mGlobalPolicies, admin);
897             }
898             if (!mLocalPolicies.contains(userId)) {
899                 return Set.of();
900             }
901             return getUserRestrictionPolicyKeysForAdminLocked(mLocalPolicies.get(userId), admin);
902         }
903     }
904 
transferPolicies(EnforcingAdmin oldAdmin, EnforcingAdmin newAdmin)905     <V> void transferPolicies(EnforcingAdmin oldAdmin, EnforcingAdmin newAdmin) {
906         synchronized (mLock) {
907             Set<PolicyKey> globalPolicies = new HashSet<>(mGlobalPolicies.keySet());
908             for (PolicyKey policy : globalPolicies) {
909                 PolicyState<?> policyState = mGlobalPolicies.get(policy);
910                 if (policyState.getPoliciesSetByAdmins().containsKey(oldAdmin)) {
911                     PolicyDefinition<V> policyDefinition =
912                             (PolicyDefinition<V>) policyState.getPolicyDefinition();
913                     PolicyValue<V> policyValue =
914                             (PolicyValue<V>) policyState.getPoliciesSetByAdmins().get(oldAdmin);
915                     setGlobalPolicy(policyDefinition, newAdmin, policyValue);
916                 }
917             }
918 
919             for (int i = 0; i < mLocalPolicies.size(); i++) {
920                 int userId = mLocalPolicies.keyAt(i);
921                 Set<PolicyKey> localPolicies = new HashSet<>(
922                         mLocalPolicies.get(userId).keySet());
923                 for (PolicyKey policy : localPolicies) {
924                     PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy);
925                     if (policyState.getPoliciesSetByAdmins().containsKey(oldAdmin)) {
926                         PolicyDefinition<V> policyDefinition =
927                                 (PolicyDefinition<V>) policyState.getPolicyDefinition();
928                         PolicyValue<V> policyValue =
929                                 (PolicyValue<V>) policyState.getPoliciesSetByAdmins().get(oldAdmin);
930                         setLocalPolicy(policyDefinition, newAdmin, policyValue, userId);
931                     }
932                 }
933             }
934         }
935         removePoliciesForAdmin(oldAdmin);
936     }
937 
getUserRestrictionPolicyKeysForAdminLocked( Map<PolicyKey, PolicyState<?>> policies, EnforcingAdmin admin)938     private Set<UserRestrictionPolicyKey> getUserRestrictionPolicyKeysForAdminLocked(
939             Map<PolicyKey, PolicyState<?>> policies,
940             EnforcingAdmin admin) {
941         Set<UserRestrictionPolicyKey> keys = new HashSet<>();
942         for (PolicyKey key : policies.keySet()) {
943             if (!policies.get(key).getPolicyDefinition().isUserRestrictionPolicy()) {
944                 continue;
945             }
946             // User restriction policies are always boolean
947             PolicyValue<Boolean> value = (PolicyValue<Boolean>) policies.get(key)
948                     .getPoliciesSetByAdmins().get(admin);
949             if (value == null || !value.getValue()) {
950                 continue;
951             }
952             keys.add((UserRestrictionPolicyKey) key);
953         }
954         return keys;
955     }
956 
hasLocalPolicyLocked(PolicyDefinition<V> policyDefinition, int userId)957     private <V> boolean hasLocalPolicyLocked(PolicyDefinition<V> policyDefinition, int userId) {
958         if (policyDefinition.isGlobalOnlyPolicy()) {
959             return false;
960         }
961         if (!mLocalPolicies.contains(userId)) {
962             return false;
963         }
964         if (!mLocalPolicies.get(userId).containsKey(policyDefinition.getPolicyKey())) {
965             return false;
966         }
967         return !mLocalPolicies.get(userId).get(policyDefinition.getPolicyKey())
968                 .getPoliciesSetByAdmins().isEmpty();
969     }
970 
hasGlobalPolicyLocked(PolicyDefinition<V> policyDefinition)971     private <V> boolean hasGlobalPolicyLocked(PolicyDefinition<V> policyDefinition) {
972         if (policyDefinition.isLocalOnlyPolicy()) {
973             return false;
974         }
975         if (!mGlobalPolicies.containsKey(policyDefinition.getPolicyKey())) {
976             return false;
977         }
978         return !mGlobalPolicies.get(policyDefinition.getPolicyKey()).getPoliciesSetByAdmins()
979                 .isEmpty();
980     }
981 
982     @NonNull
getLocalPolicyStateLocked( PolicyDefinition<V> policyDefinition, int userId)983     private <V> PolicyState<V> getLocalPolicyStateLocked(
984             PolicyDefinition<V> policyDefinition, int userId) {
985 
986         if (policyDefinition.isGlobalOnlyPolicy()) {
987             throw new IllegalArgumentException(policyDefinition.getPolicyKey() + " is a global only"
988                     + " policy.");
989         }
990 
991         if (!mLocalPolicies.contains(userId)) {
992             mLocalPolicies.put(userId, new HashMap<>());
993         }
994         if (!mLocalPolicies.get(userId).containsKey(policyDefinition.getPolicyKey())) {
995             mLocalPolicies.get(userId).put(
996                     policyDefinition.getPolicyKey(), new PolicyState<>(policyDefinition));
997         }
998         return getPolicyStateLocked(mLocalPolicies.get(userId), policyDefinition);
999     }
1000 
removeLocalPolicyStateLocked( PolicyDefinition<V> policyDefinition, int userId)1001     private <V> void removeLocalPolicyStateLocked(
1002             PolicyDefinition<V> policyDefinition, int userId) {
1003         if (!mLocalPolicies.contains(userId)) {
1004             return;
1005         }
1006         mLocalPolicies.get(userId).remove(policyDefinition.getPolicyKey());
1007     }
1008 
1009     @NonNull
getGlobalPolicyStateLocked(PolicyDefinition<V> policyDefinition)1010     private <V> PolicyState<V> getGlobalPolicyStateLocked(PolicyDefinition<V> policyDefinition) {
1011         if (policyDefinition.isLocalOnlyPolicy()) {
1012             throw new IllegalArgumentException(policyDefinition.getPolicyKey() + " is a local only"
1013                     + " policy.");
1014         }
1015 
1016         if (!mGlobalPolicies.containsKey(policyDefinition.getPolicyKey())) {
1017             mGlobalPolicies.put(
1018                     policyDefinition.getPolicyKey(), new PolicyState<>(policyDefinition));
1019         }
1020         return getPolicyStateLocked(mGlobalPolicies, policyDefinition);
1021     }
1022 
removeGlobalPolicyStateLocked(PolicyDefinition<V> policyDefinition)1023     private <V> void removeGlobalPolicyStateLocked(PolicyDefinition<V> policyDefinition) {
1024         mGlobalPolicies.remove(policyDefinition.getPolicyKey());
1025     }
1026 
getPolicyStateLocked( Map<PolicyKey, PolicyState<?>> policies, PolicyDefinition<V> policyDefinition)1027     private static <V> PolicyState<V> getPolicyStateLocked(
1028             Map<PolicyKey, PolicyState<?>> policies, PolicyDefinition<V> policyDefinition) {
1029         try {
1030             // This will not throw an exception because policyDefinition is of type V, so unless
1031             // we've created two policies with the same key but different types - we can only have
1032             // stored a PolicyState of the right type.
1033             PolicyState<V> policyState = (PolicyState<V>) policies.get(
1034                     policyDefinition.getPolicyKey());
1035             return policyState;
1036         } catch (ClassCastException exception) {
1037             // TODO: handle exception properly
1038             throw new IllegalArgumentException();
1039         }
1040     }
1041 
enforcePolicy(PolicyDefinition<V> policyDefinition, @Nullable PolicyValue<V> policyValue, int userId)1042     private <V> void enforcePolicy(PolicyDefinition<V> policyDefinition,
1043             @Nullable PolicyValue<V> policyValue, int userId) {
1044         // null policyValue means remove any enforced policies, ensure callbacks handle this
1045         // properly
1046         policyDefinition.enforcePolicy(
1047                 policyValue == null ? null : policyValue.getValue(), mContext, userId);
1048     }
1049 
sendDevicePolicyChangedToSystem(int userId)1050     private void sendDevicePolicyChangedToSystem(int userId) {
1051         Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
1052         intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1053         Bundle options = new BroadcastOptions()
1054                 .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
1055                 .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE)
1056                 .toBundle();
1057         Binder.withCleanCallingIdentity(() -> mContext.sendBroadcastAsUser(
1058                 intent,
1059                 new UserHandle(userId),
1060                 /* receiverPermissions= */ null,
1061                 options));
1062     }
1063 
sendPolicyResultToAdmin( EnforcingAdmin admin, PolicyDefinition<V> policyDefinition, int result, int userId)1064     private <V> void sendPolicyResultToAdmin(
1065             EnforcingAdmin admin, PolicyDefinition<V> policyDefinition, int result, int userId) {
1066         Intent intent = new Intent(PolicyUpdateReceiver.ACTION_DEVICE_POLICY_SET_RESULT);
1067         intent.setPackage(admin.getPackageName());
1068 
1069         Binder.withCleanCallingIdentity(() -> {
1070             List<ResolveInfo> receivers =
1071                     mContext.getPackageManager().queryBroadcastReceiversAsUser(
1072                             intent,
1073                             PackageManager.ResolveInfoFlags.of(PackageManager.GET_RECEIVERS),
1074                             admin.getUserId());
1075             if (receivers.isEmpty()) {
1076                 Log.i(TAG, "Couldn't find any receivers that handle ACTION_DEVICE_POLICY_SET_RESULT"
1077                         + " in package " + admin.getPackageName());
1078                 return;
1079             }
1080 
1081             Bundle extras = new Bundle();
1082             policyDefinition.getPolicyKey().writeToBundle(extras);
1083             extras.putInt(
1084                     EXTRA_POLICY_TARGET_USER_ID,
1085                     getTargetUser(admin.getUserId(), userId));
1086             extras.putInt(
1087                     EXTRA_POLICY_UPDATE_RESULT_KEY,
1088                     result);
1089 
1090             intent.putExtras(extras);
1091 
1092             maybeSendIntentToAdminReceivers(intent, UserHandle.of(admin.getUserId()), receivers);
1093         });
1094     }
1095 
1096     // TODO(b/261430877): Finalise the decision on which admins to send the updates to.
sendPolicyChangedToAdminsLocked( PolicyState<V> policyState, EnforcingAdmin callingAdmin, PolicyDefinition<V> policyDefinition, int userId)1097     private <V> void sendPolicyChangedToAdminsLocked(
1098             PolicyState<V> policyState,
1099             EnforcingAdmin callingAdmin,
1100             PolicyDefinition<V> policyDefinition,
1101             int userId) {
1102         for (EnforcingAdmin admin : policyState.getPoliciesSetByAdmins().keySet()) {
1103             // We're sending a separate broadcast for the calling admin with the result.
1104             if (admin.equals(callingAdmin)) {
1105                 continue;
1106             }
1107             int result = Objects.equals(
1108                     policyState.getPoliciesSetByAdmins().get(admin),
1109                     policyState.getCurrentResolvedPolicy())
1110                     ? RESULT_POLICY_SET : RESULT_FAILURE_CONFLICTING_ADMIN_POLICY;
1111             maybeSendOnPolicyChanged(
1112                     admin, policyDefinition, result, userId);
1113         }
1114     }
1115 
maybeSendOnPolicyChanged( EnforcingAdmin admin, PolicyDefinition<V> policyDefinition, int reason, int userId)1116     private <V> void maybeSendOnPolicyChanged(
1117             EnforcingAdmin admin, PolicyDefinition<V> policyDefinition, int reason,
1118             int userId) {
1119         Intent intent = new Intent(PolicyUpdateReceiver.ACTION_DEVICE_POLICY_CHANGED);
1120         intent.setPackage(admin.getPackageName());
1121 
1122         Binder.withCleanCallingIdentity(() -> {
1123             List<ResolveInfo> receivers =
1124                     mContext.getPackageManager().queryBroadcastReceiversAsUser(
1125                             intent,
1126                             PackageManager.ResolveInfoFlags.of(PackageManager.GET_RECEIVERS),
1127                             admin.getUserId());
1128             if (receivers.isEmpty()) {
1129                 Log.i(TAG, "Couldn't find any receivers that handle ACTION_DEVICE_POLICY_CHANGED"
1130                         + " in package " + admin.getPackageName());
1131                 return;
1132             }
1133 
1134             Bundle extras = new Bundle();
1135             policyDefinition.getPolicyKey().writeToBundle(extras);
1136             extras.putInt(
1137                     EXTRA_POLICY_TARGET_USER_ID,
1138                     getTargetUser(admin.getUserId(), userId));
1139             extras.putInt(EXTRA_POLICY_UPDATE_RESULT_KEY, reason);
1140             intent.putExtras(extras);
1141             intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
1142 
1143             maybeSendIntentToAdminReceivers(
1144                     intent, UserHandle.of(admin.getUserId()), receivers);
1145         });
1146     }
1147 
maybeSendIntentToAdminReceivers( Intent intent, UserHandle userHandle, List<ResolveInfo> receivers)1148     private void maybeSendIntentToAdminReceivers(
1149             Intent intent, UserHandle userHandle, List<ResolveInfo> receivers) {
1150         for (ResolveInfo resolveInfo : receivers) {
1151             if (!Manifest.permission.BIND_DEVICE_ADMIN.equals(
1152                     resolveInfo.activityInfo.permission)) {
1153                 Log.w(TAG, "Receiver " + resolveInfo.activityInfo + " is not protected by "
1154                         + "BIND_DEVICE_ADMIN permission!");
1155                 continue;
1156             }
1157             // TODO: If admins are always bound to, do I still need to set
1158             //  "BroadcastOptions.setBackgroundActivityStartsAllowed"?
1159             // TODO: maybe protect it with a permission that is granted to the role so that we
1160             //  don't accidentally send a broadcast to an admin that no longer holds the role.
1161             mContext.sendBroadcastAsUser(intent, userHandle);
1162         }
1163     }
1164 
getTargetUser(int adminUserId, int targetUserId)1165     private int getTargetUser(int adminUserId, int targetUserId) {
1166         if (targetUserId == UserHandle.USER_ALL) {
1167             return TargetUser.GLOBAL_USER_ID;
1168         }
1169         if (adminUserId == targetUserId) {
1170             return TargetUser.LOCAL_USER_ID;
1171         }
1172         if (getProfileParentId(adminUserId) == targetUserId) {
1173             return TargetUser.PARENT_USER_ID;
1174         }
1175         return TargetUser.UNKNOWN_USER_ID;
1176     }
1177 
getProfileParentId(int userId)1178     private int getProfileParentId(int userId) {
1179         return Binder.withCleanCallingIdentity(() -> {
1180             UserInfo parentUser = mUserManager.getProfileParent(userId);
1181             return parentUser != null ? parentUser.id : userId;
1182         });
1183     }
1184 
1185     /**
1186      * Starts/Stops the services that handle {@link DevicePolicyManager#ACTION_DEVICE_ADMIN_SERVICE}
1187      * in the enforcing admins for the given {@code userId}.
1188      */
updateDeviceAdminsServicesForUser( int userId, boolean enable, @NonNull String actionForLog)1189     private void updateDeviceAdminsServicesForUser(
1190             int userId, boolean enable, @NonNull String actionForLog) {
1191         if (!enable) {
1192             mDeviceAdminServiceController.stopServicesForUser(
1193                     userId, actionForLog);
1194         } else {
1195             for (EnforcingAdmin admin : getEnforcingAdminsOnUser(userId)) {
1196                 // DPCs are handled separately in DPMS, no need to reestablish the connection here.
1197                 if (admin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) {
1198                     continue;
1199                 }
1200                 mDeviceAdminServiceController.startServiceForAdmin(
1201                         admin.getPackageName(), userId, actionForLog);
1202             }
1203         }
1204     }
1205 
1206     /**
1207      * Handles internal state related to a user getting started.
1208      */
handleStartUser(int userId)1209     void handleStartUser(int userId) {
1210         updateDeviceAdminsServicesForUser(
1211                 userId, /* enable= */ true, /* actionForLog= */ "start-user");
1212     }
1213 
1214     /**
1215      * Handles internal state related to a user getting started.
1216      */
handleUnlockUser(int userId)1217     void handleUnlockUser(int userId) {
1218         updateDeviceAdminsServicesForUser(
1219                 userId, /* enable= */ true, /* actionForLog= */ "unlock-user");
1220     }
1221 
1222     /**
1223      * Handles internal state related to a user getting stopped.
1224      */
handleStopUser(int userId)1225     void handleStopUser(int userId) {
1226         updateDeviceAdminsServicesForUser(
1227                 userId, /* enable= */ false, /* actionForLog= */ "stop-user");
1228     }
1229 
1230     /**
1231      * Handles internal state related to packages getting updated.
1232      */
handlePackageChanged( @ullable String updatedPackage, int userId, @Nullable String removedDpcPackage)1233     void handlePackageChanged(
1234             @Nullable String updatedPackage, int userId, @Nullable String removedDpcPackage) {
1235         Binder.withCleanCallingIdentity(() -> {
1236             Set<EnforcingAdmin> admins = getEnforcingAdminsOnUser(userId);
1237             if (removedDpcPackage != null) {
1238                 for (EnforcingAdmin admin : admins) {
1239                     if (removedDpcPackage.equals(admin.getPackageName())) {
1240                         removePoliciesForAdmin(admin);
1241                         return;
1242                     }
1243                 }
1244             }
1245             for (EnforcingAdmin admin : admins) {
1246                 if (updatedPackage == null || updatedPackage.equals(admin.getPackageName())) {
1247                     if (!isPackageInstalled(admin.getPackageName(), userId)) {
1248                         Slogf.i(TAG, String.format(
1249                                 "Admin package %s not found for user %d, removing admin policies",
1250                                 admin.getPackageName(), userId));
1251                         // remove policies for the uninstalled package
1252                         removePoliciesForAdmin(admin);
1253                         return;
1254                     }
1255                 }
1256             }
1257             if (updatedPackage != null) {
1258                 updateDeviceAdminServiceOnPackageChanged(updatedPackage, userId);
1259                 removePersistentPreferredActivityPoliciesForPackage(updatedPackage, userId);
1260             }
1261         });
1262     }
1263 
removePersistentPreferredActivityPoliciesForPackage( @onNull String packageName, int userId)1264     private void removePersistentPreferredActivityPoliciesForPackage(
1265             @NonNull String packageName, int userId) {
1266         Set<PolicyKey> policyKeys = getLocalPolicyKeysSetByAllAdmins(
1267                 PolicyDefinition.GENERIC_PERSISTENT_PREFERRED_ACTIVITY, userId);
1268         for (PolicyKey key : policyKeys) {
1269             if (!(key instanceof IntentFilterPolicyKey)) {
1270                 throw new IllegalStateException("PolicyKey for "
1271                         + "PERSISTENT_PREFERRED_ACTIVITY is not of type "
1272                         + "IntentFilterPolicyKey");
1273             }
1274             IntentFilterPolicyKey parsedKey =
1275                     (IntentFilterPolicyKey) key;
1276             IntentFilter intentFilter = Objects.requireNonNull(parsedKey.getIntentFilter());
1277             PolicyDefinition<ComponentName> policyDefinition =
1278                     PolicyDefinition.PERSISTENT_PREFERRED_ACTIVITY(intentFilter);
1279             LinkedHashMap<EnforcingAdmin, PolicyValue<ComponentName>> policies =
1280                     getLocalPoliciesSetByAdmins(
1281                             policyDefinition,
1282                             userId);
1283             IPackageManager packageManager = AppGlobals.getPackageManager();
1284             for (EnforcingAdmin admin : policies.keySet()) {
1285                 if (policies.get(admin).getValue() != null
1286                         && policies.get(admin).getValue().getPackageName().equals(packageName)) {
1287                     try {
1288                         if (packageManager.getPackageInfo(packageName, 0, userId) == null
1289                                 || packageManager.getActivityInfo(
1290                                 policies.get(admin).getValue(), 0, userId) == null) {
1291                             Slogf.e(TAG, String.format(
1292                                     "Persistent preferred activity in package %s not found for "
1293                                             + "user %d, removing policy for admin",
1294                                     packageName, userId));
1295                             removeLocalPolicy(policyDefinition, admin, userId);
1296                         }
1297                     } catch (RemoteException re) {
1298                         // Shouldn't happen.
1299                         Slogf.wtf(TAG, "Error handling package changes", re);
1300                     }
1301                 }
1302             }
1303         }
1304     }
1305 
isPackageInstalled(String packageName, int userId)1306     private boolean isPackageInstalled(String packageName, int userId) {
1307         try {
1308             return AppGlobals.getPackageManager().getPackageInfo(
1309                     packageName, 0, userId) != null;
1310         } catch (RemoteException re) {
1311             // Shouldn't happen.
1312             Slogf.wtf(TAG, "Error handling package changes", re);
1313             return true;
1314         }
1315     }
1316 
1317     /**
1318      * Handles internal state related to a user getting removed.
1319      */
handleUserRemoved(int userId)1320     void handleUserRemoved(int userId) {
1321         removeLocalPoliciesForUser(userId);
1322         removePoliciesForAdminsOnUser(userId);
1323     }
1324 
1325     /**
1326      * Handles internal state related to a user getting created.
1327      */
handleUserCreated(UserInfo user)1328     void handleUserCreated(UserInfo user) {
1329         enforcePoliciesOnInheritableProfilesIfApplicable(user);
1330     }
1331 
1332     /**
1333      * Handles internal state related to roles getting updated.
1334      */
handleRoleChanged(@onNull String roleName, int userId)1335     void handleRoleChanged(@NonNull String roleName, int userId) {
1336         // TODO(b/256852787): handle all roles changing.
1337         if (!DEVICE_LOCK_CONTROLLER_ROLE.equals(roleName)) {
1338             // We only support device lock controller role for now.
1339             return;
1340         }
1341         String roleAuthority = EnforcingAdmin.getRoleAuthorityOf(roleName);
1342         Set<EnforcingAdmin> admins = getEnforcingAdminsOnUser(userId);
1343         for (EnforcingAdmin admin : admins) {
1344             if (admin.hasAuthority(roleAuthority)) {
1345                 admin.reloadRoleAuthorities();
1346                 // remove admin policies if role was lost
1347                 if (!admin.hasAuthority(roleAuthority)) {
1348                     removePoliciesForAdmin(admin);
1349                 }
1350             }
1351         }
1352     }
1353 
enforcePoliciesOnInheritableProfilesIfApplicable(UserInfo user)1354     private void enforcePoliciesOnInheritableProfilesIfApplicable(UserInfo user) {
1355         if (!user.isProfile()) {
1356             return;
1357         }
1358 
1359         Binder.withCleanCallingIdentity(() -> {
1360             UserProperties userProperties = mUserManager.getUserProperties(user.getUserHandle());
1361             if (userProperties == null || userProperties.getInheritDevicePolicy()
1362                     != INHERIT_DEVICE_POLICY_FROM_PARENT) {
1363                 return;
1364             }
1365 
1366             int userId = user.id;
1367             // Apply local policies present on parent to newly created child profile.
1368             UserInfo parentInfo = mUserManager.getProfileParent(userId);
1369             if (parentInfo == null || parentInfo.getUserHandle().getIdentifier() == userId) {
1370                 return;
1371             }
1372             synchronized (mLock) {
1373                 if (!mLocalPolicies.contains(parentInfo.getUserHandle().getIdentifier())) {
1374                     return;
1375                 }
1376                 for (Map.Entry<PolicyKey, PolicyState<?>> entry : mLocalPolicies.get(
1377                         parentInfo.getUserHandle().getIdentifier()).entrySet()) {
1378                     enforcePolicyOnUserLocked(userId, entry.getValue());
1379                 }
1380             }
1381         });
1382     }
1383 
enforcePolicyOnUserLocked(int userId, PolicyState<V> policyState)1384     private <V> void enforcePolicyOnUserLocked(int userId, PolicyState<V> policyState) {
1385         if (!policyState.getPolicyDefinition().isInheritable()) {
1386             return;
1387         }
1388         for (Map.Entry<EnforcingAdmin, PolicyValue<V>> enforcingAdminEntry :
1389                 policyState.getPoliciesSetByAdmins().entrySet()) {
1390             setLocalPolicy(policyState.getPolicyDefinition(),
1391                     enforcingAdminEntry.getKey(),
1392                     enforcingAdminEntry.getValue(),
1393                     userId);
1394         }
1395     }
1396 
1397     /**
1398      * Returns all current enforced policies set on the device, and the individual values set by
1399      * each admin. Global policies are returned under {@link UserHandle#ALL}.
1400      */
1401     @NonNull
getDevicePolicyState()1402     DevicePolicyState getDevicePolicyState() {
1403         synchronized (mLock) {
1404             Map<UserHandle, Map<PolicyKey, android.app.admin.PolicyState<?>>> policies =
1405                     new HashMap<>();
1406             for (int i = 0; i < mLocalPolicies.size(); i++) {
1407                 UserHandle user = UserHandle.of(mLocalPolicies.keyAt(i));
1408                 policies.put(user, new HashMap<>());
1409                 for (PolicyKey policyKey : mLocalPolicies.valueAt(i).keySet()) {
1410                     policies.get(user).put(
1411                             policyKey,
1412                             mLocalPolicies.valueAt(i).get(policyKey).getParcelablePolicyState());
1413                 }
1414             }
1415             if (!mGlobalPolicies.isEmpty()) {
1416                 policies.put(UserHandle.ALL, new HashMap<>());
1417                 for (PolicyKey policyKey : mGlobalPolicies.keySet()) {
1418                     policies.get(UserHandle.ALL).put(
1419                             policyKey,
1420                             mGlobalPolicies.get(policyKey).getParcelablePolicyState());
1421                 }
1422             }
1423             return new DevicePolicyState(policies);
1424         }
1425     }
1426 
1427     /**
1428      * Removes all local and global policies set by that admin.
1429      */
removePoliciesForAdmin(EnforcingAdmin admin)1430     void removePoliciesForAdmin(EnforcingAdmin admin) {
1431         synchronized (mLock) {
1432             Set<PolicyKey> globalPolicies = new HashSet<>(mGlobalPolicies.keySet());
1433             for (PolicyKey policy : globalPolicies) {
1434                 PolicyState<?> policyState = mGlobalPolicies.get(policy);
1435                 if (policyState.getPoliciesSetByAdmins().containsKey(admin)) {
1436                     removeGlobalPolicy(policyState.getPolicyDefinition(), admin);
1437                 }
1438             }
1439 
1440             for (int i = 0; i < mLocalPolicies.size(); i++) {
1441                 Set<PolicyKey> localPolicies = new HashSet<>(
1442                         mLocalPolicies.get(mLocalPolicies.keyAt(i)).keySet());
1443                 for (PolicyKey policy : localPolicies) {
1444                     PolicyState<?> policyState = mLocalPolicies.get(
1445                             mLocalPolicies.keyAt(i)).get(policy);
1446                     if (policyState.getPoliciesSetByAdmins().containsKey(admin)) {
1447                         removeLocalPolicy(
1448                                 policyState.getPolicyDefinition(), admin, mLocalPolicies.keyAt(i));
1449                     }
1450                 }
1451             }
1452         }
1453     }
1454 
1455     /**
1456      * Removes all local policies for the provided {@code userId}.
1457      */
removeLocalPoliciesForUser(int userId)1458     private void removeLocalPoliciesForUser(int userId) {
1459         synchronized (mLock) {
1460             if (!mLocalPolicies.contains(userId)) {
1461                 // No policies on user
1462                 return;
1463             }
1464 
1465             Set<PolicyKey> localPolicies = new HashSet<>(mLocalPolicies.get(userId).keySet());
1466             for (PolicyKey policy : localPolicies) {
1467                 PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy);
1468                 Set<EnforcingAdmin> admins = new HashSet<>(
1469                         policyState.getPoliciesSetByAdmins().keySet());
1470                 for (EnforcingAdmin admin : admins) {
1471                     removeLocalPolicy(
1472                             policyState.getPolicyDefinition(), admin, userId);
1473                 }
1474             }
1475 
1476             mLocalPolicies.remove(userId);
1477         }
1478     }
1479 
1480     /**
1481      * Removes all local and global policies for admins installed in the provided
1482      * {@code userId}.
1483      */
removePoliciesForAdminsOnUser(int userId)1484     private void removePoliciesForAdminsOnUser(int userId) {
1485         Set<EnforcingAdmin> admins = getEnforcingAdminsOnUser(userId);
1486 
1487         for (EnforcingAdmin admin : admins) {
1488             removePoliciesForAdmin(admin);
1489         }
1490     }
1491 
1492     /**
1493      * Reestablishes the service that handles
1494      * {@link DevicePolicyManager#ACTION_DEVICE_ADMIN_SERVICE} in the enforcing admin if the package
1495      * was updated, as a package update results in the persistent connection getting reset.
1496      */
updateDeviceAdminServiceOnPackageChanged( @onNull String updatedPackage, int userId)1497     private void updateDeviceAdminServiceOnPackageChanged(
1498             @NonNull String updatedPackage, int userId) {
1499         for (EnforcingAdmin admin : getEnforcingAdminsOnUser(userId)) {
1500             // DPCs are handled separately in DPMS, no need to reestablish the connection here.
1501             if (admin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) {
1502                 continue;
1503             }
1504             if (updatedPackage.equals(admin.getPackageName())) {
1505                 mDeviceAdminServiceController.startServiceForAdmin(
1506                         updatedPackage, userId, /* actionForLog= */ "package-broadcast");
1507             }
1508         }
1509     }
1510 
1511     /**
1512      * Called after an admin policy has been added to start binding to the admin if a connection
1513      * was not already established.
1514      */
updateDeviceAdminServiceOnPolicyAddLocked(@onNull EnforcingAdmin enforcingAdmin)1515     private void updateDeviceAdminServiceOnPolicyAddLocked(@NonNull EnforcingAdmin enforcingAdmin) {
1516         int userId = enforcingAdmin.getUserId();
1517 
1518         if (mEnforcingAdmins.contains(userId)
1519                 && mEnforcingAdmins.get(userId).contains(enforcingAdmin)) {
1520             return;
1521         }
1522 
1523         if (!mEnforcingAdmins.contains(enforcingAdmin.getUserId())) {
1524             mEnforcingAdmins.put(enforcingAdmin.getUserId(), new HashSet<>());
1525         }
1526         mEnforcingAdmins.get(enforcingAdmin.getUserId()).add(enforcingAdmin);
1527 
1528         // A connection is established with DPCs as soon as they are provisioned, so no need to
1529         // connect when a policy is set.
1530         if (enforcingAdmin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) {
1531             return;
1532         }
1533         mDeviceAdminServiceController.startServiceForAdmin(
1534                 enforcingAdmin.getPackageName(),
1535                 userId,
1536                 /* actionForLog= */ "policy-added");
1537     }
1538 
1539     /**
1540      * Called after an admin policy has been removed to stop binding to the admin if they no longer
1541      * have any policies set.
1542      */
updateDeviceAdminServiceOnPolicyRemoveLocked( @onNull EnforcingAdmin enforcingAdmin)1543     private void updateDeviceAdminServiceOnPolicyRemoveLocked(
1544             @NonNull EnforcingAdmin enforcingAdmin) {
1545         if (doesAdminHavePoliciesLocked(enforcingAdmin)) {
1546             return;
1547         }
1548         int userId = enforcingAdmin.getUserId();
1549         if (mEnforcingAdmins.contains(userId)) {
1550             mEnforcingAdmins.get(userId).remove(enforcingAdmin);
1551             if (mEnforcingAdmins.get(userId).isEmpty()) {
1552                 mEnforcingAdmins.remove(enforcingAdmin.getUserId());
1553             }
1554         }
1555 
1556         // TODO(b/263364434): centralise handling in one place.
1557         // DPCs rely on a constant connection being established as soon as they are provisioned,
1558         // so we shouldn't disconnect it even if they no longer have policies set.
1559         if (enforcingAdmin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) {
1560             return;
1561         }
1562         mDeviceAdminServiceController.stopServiceForAdmin(
1563                 enforcingAdmin.getPackageName(),
1564                 userId,
1565                 /* actionForLog= */ "policy-removed");
1566     }
1567 
doesAdminHavePoliciesLocked(@onNull EnforcingAdmin enforcingAdmin)1568     private boolean doesAdminHavePoliciesLocked(@NonNull EnforcingAdmin enforcingAdmin) {
1569         for (PolicyKey policy : mGlobalPolicies.keySet()) {
1570             PolicyState<?> policyState = mGlobalPolicies.get(policy);
1571             if (policyState.getPoliciesSetByAdmins().containsKey(enforcingAdmin)) {
1572                 return true;
1573             }
1574         }
1575         for (int i = 0; i < mLocalPolicies.size(); i++) {
1576             for (PolicyKey policy : mLocalPolicies.get(mLocalPolicies.keyAt(i)).keySet()) {
1577                 PolicyState<?> policyState = mLocalPolicies.get(
1578                         mLocalPolicies.keyAt(i)).get(policy);
1579                 if (policyState.getPoliciesSetByAdmins().containsKey(enforcingAdmin)) {
1580                     return true;
1581                 }
1582             }
1583         }
1584         return false;
1585     }
1586 
1587     @NonNull
getEnforcingAdminsOnUser(int userId)1588     private Set<EnforcingAdmin> getEnforcingAdminsOnUser(int userId) {
1589         synchronized (mLock) {
1590             return mEnforcingAdmins.contains(userId)
1591                     ? new HashSet<>(mEnforcingAdmins.get(userId)) : Collections.emptySet();
1592         }
1593     }
1594 
1595     /**
1596      * Calculate the size of a policy in bytes
1597      */
sizeOf(PolicyValue<V> value)1598     private static <V> int sizeOf(PolicyValue<V> value) {
1599         try {
1600             Parcel parcel = Parcel.obtain();
1601             parcel.writeParcelable(value, /* flags= */ 0);
1602 
1603             parcel.setDataPosition(0);
1604 
1605             byte[] bytes;
1606 
1607             bytes = parcel.marshall();
1608             return bytes.length;
1609         } catch (Exception e) {
1610             Log.e(TAG, "Error calculating size of policy: " + e);
1611             return 0;
1612         }
1613     }
1614 
1615     /**
1616      * Checks if the policy already exists and removes the current size to prevent recording the
1617      * same policy twice.
1618      *
1619      * Checks if the new sum of the size of all policies is less than the maximum sum of policies
1620      * size per admin and returns true.
1621      *
1622      * If the policy size limit is reached then send policy result to admin and return false.
1623      */
handleAdminPolicySizeLimit(PolicyState<V> policyState, EnforcingAdmin admin, PolicyValue<V> value, PolicyDefinition<V> policyDefinition, int userId)1624     private <V> boolean handleAdminPolicySizeLimit(PolicyState<V> policyState, EnforcingAdmin admin,
1625             PolicyValue<V> value, PolicyDefinition<V> policyDefinition, int userId) {
1626         int currentAdminPoliciesSize = 0;
1627         int existingPolicySize = 0;
1628         if (mAdminPolicySize.contains(admin.getUserId())
1629                 && mAdminPolicySize.get(
1630                 admin.getUserId()).containsKey(admin)) {
1631             currentAdminPoliciesSize = mAdminPolicySize.get(admin.getUserId()).get(admin);
1632         }
1633         if (policyState.getPoliciesSetByAdmins().containsKey(admin)) {
1634             existingPolicySize = sizeOf(policyState.getPoliciesSetByAdmins().get(admin));
1635         }
1636         int policySize = sizeOf(value);
1637 
1638         // Policy size limit is disabled if mPolicySizeLimit is -1.
1639         if (mPolicySizeLimit == -1
1640                 || currentAdminPoliciesSize + policySize - existingPolicySize < mPolicySizeLimit) {
1641             increasePolicySizeForAdmin(
1642                     admin, /* policySizeDiff = */ policySize - existingPolicySize);
1643             return true;
1644         } else {
1645             Log.w(TAG, "Admin " + admin + "reached max allowed storage limit.");
1646             sendPolicyResultToAdmin(
1647                     admin,
1648                     policyDefinition,
1649                     RESULT_FAILURE_STORAGE_LIMIT_REACHED,
1650                     userId);
1651             return false;
1652         }
1653     }
1654 
1655     /**
1656      * Increase the int in mAdminPolicySize representing the size of the sum of all
1657      * active policies for that admin.
1658      */
increasePolicySizeForAdmin(EnforcingAdmin admin, int policySizeDiff)1659     private <V> void increasePolicySizeForAdmin(EnforcingAdmin admin, int policySizeDiff) {
1660         if (!mAdminPolicySize.contains(admin.getUserId())) {
1661             mAdminPolicySize.put(admin.getUserId(), new HashMap<>());
1662         }
1663         if (!mAdminPolicySize.get(admin.getUserId()).containsKey(admin)) {
1664             mAdminPolicySize.get(admin.getUserId()).put(admin, /* size= */ 0);
1665         }
1666         mAdminPolicySize.get(admin.getUserId()).put(admin,
1667                 mAdminPolicySize.get(admin.getUserId()).get(admin) + policySizeDiff);
1668     }
1669 
1670     /**
1671      * Decrease the int in mAdminPolicySize representing the size of the sum of all
1672      * active policies for that admin.
1673      */
decreasePolicySizeForAdmin(PolicyState<V> policyState, EnforcingAdmin admin)1674     private <V> void decreasePolicySizeForAdmin(PolicyState<V> policyState, EnforcingAdmin admin) {
1675         if (!policyState.getPoliciesSetByAdmins().containsKey(admin)
1676                 || !mAdminPolicySize.contains(admin.getUserId())
1677                 || !mAdminPolicySize.get(admin.getUserId()).containsKey(admin)) {
1678             return;
1679         }
1680         mAdminPolicySize.get(admin.getUserId()).put(admin,
1681                 mAdminPolicySize.get(admin.getUserId()).get(admin) - sizeOf(
1682                         policyState.getPoliciesSetByAdmins().get(admin)));
1683         if (mAdminPolicySize.get(admin.getUserId()).get(admin) <= 0) {
1684             mAdminPolicySize.get(admin.getUserId()).remove(admin);
1685         }
1686         if (mAdminPolicySize.get(admin.getUserId()).isEmpty()) {
1687             mAdminPolicySize.remove(admin.getUserId());
1688         }
1689     }
1690 
1691     /**
1692      * Updates the max allowed size limit for policies per admin. Setting it to -1, disables
1693      * the limitation.
1694      */
setMaxPolicyStorageLimit(int storageLimit)1695     void setMaxPolicyStorageLimit(int storageLimit) {
1696         mPolicySizeLimit = storageLimit;
1697     }
1698 
1699     /**
1700      * Returns the max allowed size limit for policies per admin. -1 means the limitation is
1701      * disabled.
1702      */
getMaxPolicyStorageLimit()1703     int getMaxPolicyStorageLimit() {
1704         return mPolicySizeLimit;
1705     }
1706 
getPolicySizeForAdmin(EnforcingAdmin admin)1707     int getPolicySizeForAdmin(EnforcingAdmin admin) {
1708         if (mAdminPolicySize.contains(admin.getUserId())
1709                 && mAdminPolicySize.get(
1710                 admin.getUserId()).containsKey(admin)) {
1711             return mAdminPolicySize.get(admin.getUserId()).get(admin);
1712         }
1713         return 0;
1714     }
1715 
dump(IndentingPrintWriter pw)1716     public void dump(IndentingPrintWriter pw) {
1717         synchronized (mLock) {
1718             pw.println("Local Policies: ");
1719             pw.increaseIndent();
1720             for (int i = 0; i < mLocalPolicies.size(); i++) {
1721                 int userId = mLocalPolicies.keyAt(i);
1722                 pw.printf("User %d:\n", userId);
1723                 pw.increaseIndent();
1724                 for (PolicyKey policy : mLocalPolicies.get(userId).keySet()) {
1725                     PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy);
1726                     policyState.dump(pw);
1727                     pw.println();
1728                 }
1729                 pw.decreaseIndent();
1730             }
1731             pw.decreaseIndent();
1732             pw.println();
1733 
1734             pw.println("Global Policies: ");
1735             pw.increaseIndent();
1736             for (PolicyKey policy : mGlobalPolicies.keySet()) {
1737                 PolicyState<?> policyState = mGlobalPolicies.get(policy);
1738                 policyState.dump(pw);
1739                 pw.println();
1740             }
1741             pw.decreaseIndent();
1742             if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
1743                 pw.println();
1744 
1745                 pw.println("Default admin policy size limit: " + DEFAULT_POLICY_SIZE_LIMIT);
1746                 pw.println("Current admin policy size limit: " + mPolicySizeLimit);
1747                 pw.println("Admin Policies size: ");
1748                 for (int i = 0; i < mAdminPolicySize.size(); i++) {
1749                     int userId = mAdminPolicySize.keyAt(i);
1750                     pw.printf("User %d:\n", userId);
1751                     pw.increaseIndent();
1752                     for (EnforcingAdmin admin : mAdminPolicySize.get(userId).keySet()) {
1753                         pw.printf("Admin : " + admin + " : " + mAdminPolicySize.get(userId).get(
1754                                 admin));
1755                         pw.println();
1756                     }
1757                     pw.decreaseIndent();
1758                 }
1759                 pw.decreaseIndent();
1760             }
1761         }
1762     }
1763 
write()1764     private void write() {
1765         synchronized (mLock) {
1766             Log.d(TAG, "Writing device policies to file.");
1767             new DevicePoliciesReaderWriter().writeToFileLocked();
1768         }
1769     }
1770 
1771     // TODO(b/256852787): trigger resolving logic after loading policies as roles are recalculated
1772     //  and could result in a different enforced policy
load()1773     void load() {
1774         Log.d(TAG, "Reading device policies from file.");
1775         synchronized (mLock) {
1776             clear();
1777             new DevicePoliciesReaderWriter().readFromFileLocked();
1778         }
1779     }
1780 
1781     /**
1782      * Create a backup of the policy engine XML file, so that we can recover previous state
1783      * in case some data-loss bug is triggered e.g. during migration.
1784      *
1785      * Backup is only created if one with the same ID does not exist yet.
1786      */
createBackup(String backupId)1787     void createBackup(String backupId) {
1788         synchronized (mLock) {
1789             DevicePoliciesReaderWriter.createBackup(backupId);
1790         }
1791     }
1792 
reapplyAllPoliciesOnBootLocked()1793     <V> void reapplyAllPoliciesOnBootLocked() {
1794         for (PolicyKey policy : mGlobalPolicies.keySet()) {
1795             PolicyState<?> policyState = mGlobalPolicies.get(policy);
1796             // Policy definition and value will always be of the same type
1797             PolicyDefinition<V> policyDefinition =
1798                     (PolicyDefinition<V>) policyState.getPolicyDefinition();
1799             if (!policyDefinition.shouldSkipEnforcementIfNotChanged()) {
1800                 PolicyValue<V> policyValue =
1801                         (PolicyValue<V>) policyState.getCurrentResolvedPolicy();
1802                 enforcePolicy(policyDefinition, policyValue, UserHandle.USER_ALL);
1803             }
1804         }
1805         for (int i = 0; i < mLocalPolicies.size(); i++) {
1806             int userId = mLocalPolicies.keyAt(i);
1807             for (PolicyKey policy : mLocalPolicies.get(userId).keySet()) {
1808                 PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy);
1809                 // Policy definition and value will always be of the same type
1810                 PolicyDefinition<V> policyDefinition =
1811                         (PolicyDefinition<V>) policyState.getPolicyDefinition();
1812                 if (!policyDefinition.shouldSkipEnforcementIfNotChanged()) {
1813                     PolicyValue<V> policyValue =
1814                             (PolicyValue<V>) policyState.getCurrentResolvedPolicy();
1815                     enforcePolicy(policyDefinition, policyValue, userId);
1816                 }
1817             }
1818         }
1819     }
1820 
1821     /**
1822      * Clear all policies set in the policy engine.
1823      *
1824      * <p>Note that this doesn't clear any enforcements, it only clears the data structures.
1825      */
clearAllPolicies()1826     void clearAllPolicies() {
1827         clear();
1828         write();
1829     }
1830 
clear()1831     private void clear() {
1832         synchronized (mLock) {
1833             mGlobalPolicies.clear();
1834             mLocalPolicies.clear();
1835             mEnforcingAdmins.clear();
1836             mAdminPolicySize.clear();
1837         }
1838     }
1839 
checkFor2gFailure(@onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin)1840     private <V> boolean checkFor2gFailure(@NonNull PolicyDefinition<V> policyDefinition,
1841             @NonNull EnforcingAdmin enforcingAdmin) {
1842         if (!policyDefinition.getPolicyKey().getIdentifier().equals(
1843                 CELLULAR_2G_USER_RESTRICTION_ID)) {
1844             return false;
1845         }
1846 
1847         boolean isCapabilitySupported;
1848         try {
1849             isCapabilitySupported = mContext.getSystemService(
1850                     TelephonyManager.class).isRadioInterfaceCapabilitySupported(
1851                     TelephonyManager.CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK);
1852         } catch (IllegalStateException e) {
1853             // isRadioInterfaceCapabilitySupported can throw if there is no Telephony
1854             // service initialized.
1855             isCapabilitySupported = false;
1856         }
1857 
1858         if (!isCapabilitySupported) {
1859             sendPolicyResultToAdmin(
1860                     enforcingAdmin,
1861                     policyDefinition,
1862                     RESULT_FAILURE_HARDWARE_LIMITATION,
1863                     UserHandle.USER_ALL);
1864             return true;
1865         }
1866 
1867         return false;
1868     }
1869 
1870     /**
1871      * For PackageSetUnion policies, we can't simply compare the resolved policy against the admin's
1872      * policy for equality to determine if the admin has applied the policy successfully, instead
1873      * the admin's policy should be considered applied successfully as long as its policy is subset
1874      * of the resolved policy. This method controls which policies should use this special logic.
1875      */
shouldApplyPackageSetUnionPolicyHack(PolicyDefinition<V> policy)1876     private <V> boolean shouldApplyPackageSetUnionPolicyHack(PolicyDefinition<V> policy) {
1877         String policyKey =  policy.getPolicyKey().getIdentifier();
1878         return policyKey.equals(USER_CONTROL_DISABLED_PACKAGES_POLICY)
1879                 || policyKey.equals(PACKAGES_SUSPENDED_POLICY);
1880     }
1881 
1882     private class DevicePoliciesReaderWriter {
1883         private static final String DEVICE_POLICIES_XML = "device_policy_state.xml";
1884         private static final String BACKUP_DIRECTORY = "device_policy_backups";
1885         private static final String BACKUP_FILENAME = "device_policy_state.%s.xml";
1886         private static final String TAG_LOCAL_POLICY_ENTRY = "local-policy-entry";
1887         private static final String TAG_GLOBAL_POLICY_ENTRY = "global-policy-entry";
1888         private static final String TAG_POLICY_STATE_ENTRY = "policy-state-entry";
1889         private static final String TAG_POLICY_KEY_ENTRY = "policy-key-entry";
1890         private static final String TAG_ENFORCING_ADMINS_ENTRY = "enforcing-admins-entry";
1891         private static final String TAG_ENFORCING_ADMIN_AND_SIZE = "enforcing-admin-and-size";
1892         private static final String TAG_ENFORCING_ADMIN = "enforcing-admin";
1893         private static final String TAG_POLICY_SUM_SIZE = "policy-sum-size";
1894         private static final String TAG_MAX_POLICY_SIZE_LIMIT = "max-policy-size-limit";
1895         private static final String ATTR_USER_ID = "user-id";
1896         private static final String ATTR_POLICY_SUM_SIZE = "size";
1897 
1898         private final File mFile;
1899 
getFileName()1900         private static File getFileName() {
1901             return new File(Environment.getDataSystemDirectory(), DEVICE_POLICIES_XML);
1902         }
DevicePoliciesReaderWriter()1903         private DevicePoliciesReaderWriter() {
1904             mFile = getFileName();
1905         }
1906 
createBackup(String backupId)1907         public static void createBackup(String backupId) {
1908             try {
1909                 File backupDirectory = new File(Environment.getDataSystemDirectory(),
1910                         BACKUP_DIRECTORY);
1911                 backupDirectory.mkdir();
1912                 Path backupPath = Path.of(backupDirectory.getPath(),
1913                         BACKUP_FILENAME.formatted(backupId));
1914                 if (backupPath.toFile().exists()) {
1915                     Log.w(TAG, "Backup already exist: " + backupPath);
1916                 } else {
1917                     Files.copy(getFileName().toPath(), backupPath,
1918                             StandardCopyOption.REPLACE_EXISTING);
1919                     Log.i(TAG, "Backup created at " + backupPath);
1920                 }
1921             } catch (Exception e) {
1922                 Log.e(TAG, "Cannot create backup " + backupId, e);
1923             }
1924         }
1925 
writeToFileLocked()1926         void writeToFileLocked() {
1927             Log.d(TAG, "Writing to " + mFile);
1928 
1929             AtomicFile f = new AtomicFile(mFile);
1930             FileOutputStream outputStream = null;
1931             try {
1932                 outputStream = f.startWrite();
1933                 TypedXmlSerializer out = Xml.resolveSerializer(outputStream);
1934 
1935                 out.startDocument(null, true);
1936 
1937                 // Actual content
1938                 writeInner(out);
1939 
1940                 out.endDocument();
1941                 out.flush();
1942 
1943                 // Commit the content.
1944                 f.finishWrite(outputStream);
1945                 outputStream = null;
1946 
1947             } catch (IOException e) {
1948                 Log.e(TAG, "Exception when writing", e);
1949                 if (outputStream != null) {
1950                     f.failWrite(outputStream);
1951                 }
1952             }
1953         }
1954 
1955         // TODO(b/256846294): Add versioning to read/write
writeInner(TypedXmlSerializer serializer)1956         void writeInner(TypedXmlSerializer serializer) throws IOException {
1957             writeLocalPoliciesInner(serializer);
1958             writeGlobalPoliciesInner(serializer);
1959             writeEnforcingAdminsInner(serializer);
1960             writeEnforcingAdminSizeInner(serializer);
1961             writeMaxPolicySizeInner(serializer);
1962         }
1963 
writeLocalPoliciesInner(TypedXmlSerializer serializer)1964         private void writeLocalPoliciesInner(TypedXmlSerializer serializer) throws IOException {
1965             if (mLocalPolicies != null) {
1966                 for (int i = 0; i < mLocalPolicies.size(); i++) {
1967                     int userId = mLocalPolicies.keyAt(i);
1968                     for (Map.Entry<PolicyKey, PolicyState<?>> policy : mLocalPolicies.get(
1969                             userId).entrySet()) {
1970                         serializer.startTag(/* namespace= */ null, TAG_LOCAL_POLICY_ENTRY);
1971 
1972                         serializer.attributeInt(/* namespace= */ null, ATTR_USER_ID, userId);
1973 
1974                         serializer.startTag(/* namespace= */ null, TAG_POLICY_KEY_ENTRY);
1975                         policy.getKey().saveToXml(serializer);
1976                         serializer.endTag(/* namespace= */ null, TAG_POLICY_KEY_ENTRY);
1977 
1978                         serializer.startTag(/* namespace= */ null, TAG_POLICY_STATE_ENTRY);
1979                         policy.getValue().saveToXml(serializer);
1980                         serializer.endTag(/* namespace= */ null, TAG_POLICY_STATE_ENTRY);
1981 
1982                         serializer.endTag(/* namespace= */ null, TAG_LOCAL_POLICY_ENTRY);
1983                     }
1984                 }
1985             }
1986         }
1987 
writeGlobalPoliciesInner(TypedXmlSerializer serializer)1988         private void writeGlobalPoliciesInner(TypedXmlSerializer serializer) throws IOException {
1989             if (mGlobalPolicies != null) {
1990                 for (Map.Entry<PolicyKey, PolicyState<?>> policy : mGlobalPolicies.entrySet()) {
1991                     serializer.startTag(/* namespace= */ null, TAG_GLOBAL_POLICY_ENTRY);
1992 
1993                     serializer.startTag(/* namespace= */ null, TAG_POLICY_KEY_ENTRY);
1994                     policy.getKey().saveToXml(serializer);
1995                     serializer.endTag(/* namespace= */ null, TAG_POLICY_KEY_ENTRY);
1996 
1997                     serializer.startTag(/* namespace= */ null, TAG_POLICY_STATE_ENTRY);
1998                     policy.getValue().saveToXml(serializer);
1999                     serializer.endTag(/* namespace= */ null, TAG_POLICY_STATE_ENTRY);
2000 
2001                     serializer.endTag(/* namespace= */ null, TAG_GLOBAL_POLICY_ENTRY);
2002                 }
2003             }
2004         }
2005 
writeEnforcingAdminsInner(TypedXmlSerializer serializer)2006         private void writeEnforcingAdminsInner(TypedXmlSerializer serializer) throws IOException {
2007             if (mEnforcingAdmins != null) {
2008                 for (int i = 0; i < mEnforcingAdmins.size(); i++) {
2009                     int userId = mEnforcingAdmins.keyAt(i);
2010                     for (EnforcingAdmin admin : mEnforcingAdmins.get(userId)) {
2011                         serializer.startTag(/* namespace= */ null, TAG_ENFORCING_ADMINS_ENTRY);
2012                         admin.saveToXml(serializer);
2013                         serializer.endTag(/* namespace= */ null, TAG_ENFORCING_ADMINS_ENTRY);
2014                     }
2015                 }
2016             }
2017         }
2018 
writeEnforcingAdminSizeInner(TypedXmlSerializer serializer)2019         private void writeEnforcingAdminSizeInner(TypedXmlSerializer serializer)
2020                 throws IOException {
2021             if (Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
2022                 if (mAdminPolicySize != null) {
2023                     for (int i = 0; i < mAdminPolicySize.size(); i++) {
2024                         int userId = mAdminPolicySize.keyAt(i);
2025                         for (EnforcingAdmin admin : mAdminPolicySize.get(
2026                                 userId).keySet()) {
2027                             serializer.startTag(/* namespace= */ null,
2028                                     TAG_ENFORCING_ADMIN_AND_SIZE);
2029                             serializer.startTag(/* namespace= */ null, TAG_ENFORCING_ADMIN);
2030                             admin.saveToXml(serializer);
2031                             serializer.endTag(/* namespace= */ null, TAG_ENFORCING_ADMIN);
2032                             serializer.startTag(/* namespace= */ null, TAG_POLICY_SUM_SIZE);
2033                             serializer.attributeInt(/* namespace= */ null, ATTR_POLICY_SUM_SIZE,
2034                                     mAdminPolicySize.get(userId).get(admin));
2035                             serializer.endTag(/* namespace= */ null, TAG_POLICY_SUM_SIZE);
2036                             serializer.endTag(/* namespace= */ null, TAG_ENFORCING_ADMIN_AND_SIZE);
2037                         }
2038                     }
2039                 }
2040             }
2041         }
2042 
writeMaxPolicySizeInner(TypedXmlSerializer serializer)2043         private void writeMaxPolicySizeInner(TypedXmlSerializer serializer)
2044                 throws IOException {
2045             if (!Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
2046                 return;
2047             }
2048             serializer.startTag(/* namespace= */ null, TAG_MAX_POLICY_SIZE_LIMIT);
2049             serializer.attributeInt(
2050                     /* namespace= */ null, ATTR_POLICY_SUM_SIZE, mPolicySizeLimit);
2051             serializer.endTag(/* namespace= */ null, TAG_MAX_POLICY_SIZE_LIMIT);
2052         }
2053 
readFromFileLocked()2054         void readFromFileLocked() {
2055             if (!mFile.exists()) {
2056                 Log.d(TAG, "" + mFile + " doesn't exist");
2057                 return;
2058             }
2059 
2060             Log.d(TAG, "Reading from " + mFile);
2061             AtomicFile f = new AtomicFile(mFile);
2062             InputStream input = null;
2063             try {
2064                 input = f.openRead();
2065                 TypedXmlPullParser parser = Xml.resolvePullParser(input);
2066 
2067                 readInner(parser);
2068 
2069             } catch (XmlPullParserException | IOException | ClassNotFoundException e) {
2070                 Slogf.wtf(TAG, "Error parsing resources file", e);
2071             } finally {
2072                 IoUtils.closeQuietly(input);
2073             }
2074         }
2075 
readInner(TypedXmlPullParser parser)2076         private void readInner(TypedXmlPullParser parser)
2077                 throws IOException, XmlPullParserException, ClassNotFoundException {
2078             int outerDepth = parser.getDepth();
2079             while (XmlUtils.nextElementWithin(parser, outerDepth)) {
2080                 String tag = parser.getName();
2081                 switch (tag) {
2082                     case TAG_LOCAL_POLICY_ENTRY:
2083                         readLocalPoliciesInner(parser);
2084                         break;
2085                     case TAG_GLOBAL_POLICY_ENTRY:
2086                         readGlobalPoliciesInner(parser);
2087                         break;
2088                     case TAG_ENFORCING_ADMINS_ENTRY:
2089                         readEnforcingAdminsInner(parser);
2090                         break;
2091                     case TAG_ENFORCING_ADMIN_AND_SIZE:
2092                         readEnforcingAdminAndSizeInner(parser);
2093                         break;
2094                     case TAG_MAX_POLICY_SIZE_LIMIT:
2095                         readMaxPolicySizeInner(parser);
2096                         break;
2097                     default:
2098                         Slogf.wtf(TAG, "Unknown tag " + tag);
2099                 }
2100             }
2101         }
2102 
readLocalPoliciesInner(TypedXmlPullParser parser)2103         private void readLocalPoliciesInner(TypedXmlPullParser parser)
2104                 throws XmlPullParserException, IOException {
2105             int userId = parser.getAttributeInt(/* namespace= */ null, ATTR_USER_ID);
2106             PolicyKey policyKey = null;
2107             PolicyState<?> policyState = null;
2108             int outerDepth = parser.getDepth();
2109             while (XmlUtils.nextElementWithin(parser, outerDepth)) {
2110                 String tag = parser.getName();
2111                 switch (tag) {
2112                     case TAG_POLICY_KEY_ENTRY:
2113                         policyKey = PolicyDefinition.readPolicyKeyFromXml(parser);
2114                         break;
2115                     case TAG_POLICY_STATE_ENTRY:
2116                         policyState = PolicyState.readFromXml(parser);
2117                         break;
2118                     default:
2119                         Slogf.wtf(TAG, "Unknown tag for local policy entry" + tag);
2120                 }
2121             }
2122 
2123             if (policyKey != null && policyState != null) {
2124                 if (!mLocalPolicies.contains(userId)) {
2125                     mLocalPolicies.put(userId, new HashMap<>());
2126                 }
2127                 mLocalPolicies.get(userId).put(policyKey, policyState);
2128             } else {
2129                 Slogf.wtf(TAG, "Error parsing local policy, policyKey is "
2130                         + (policyKey == null ? "null" : policyKey) + ", and policyState is "
2131                         + (policyState == null ? "null" : policyState) + ".");
2132             }
2133         }
2134 
readGlobalPoliciesInner(TypedXmlPullParser parser)2135         private void readGlobalPoliciesInner(TypedXmlPullParser parser)
2136                 throws IOException, XmlPullParserException {
2137             PolicyKey policyKey = null;
2138             PolicyState<?> policyState = null;
2139             int outerDepth = parser.getDepth();
2140             while (XmlUtils.nextElementWithin(parser, outerDepth)) {
2141                 String tag = parser.getName();
2142                 switch (tag) {
2143                     case TAG_POLICY_KEY_ENTRY:
2144                         policyKey = PolicyDefinition.readPolicyKeyFromXml(parser);
2145                         break;
2146                     case TAG_POLICY_STATE_ENTRY:
2147                         policyState = PolicyState.readFromXml(parser);
2148                         break;
2149                     default:
2150                         Slogf.wtf(TAG, "Unknown tag for local policy entry" + tag);
2151                 }
2152             }
2153 
2154             if (policyKey != null && policyState != null) {
2155                 mGlobalPolicies.put(policyKey, policyState);
2156             } else {
2157                 Slogf.wtf(TAG, "Error parsing global policy, policyKey is "
2158                         + (policyKey == null ? "null" : policyKey) + ", and policyState is "
2159                         + (policyState == null ? "null" : policyState) + ".");
2160             }
2161         }
2162 
readEnforcingAdminsInner(TypedXmlPullParser parser)2163         private void readEnforcingAdminsInner(TypedXmlPullParser parser)
2164                 throws XmlPullParserException {
2165             EnforcingAdmin admin = EnforcingAdmin.readFromXml(parser);
2166             if (admin == null) {
2167                 Slogf.wtf(TAG, "Error parsing enforcingAdmins, EnforcingAdmin is null.");
2168                 return;
2169             }
2170             if (!mEnforcingAdmins.contains(admin.getUserId())) {
2171                 mEnforcingAdmins.put(admin.getUserId(), new HashSet<>());
2172             }
2173             mEnforcingAdmins.get(admin.getUserId()).add(admin);
2174         }
2175 
readEnforcingAdminAndSizeInner(TypedXmlPullParser parser)2176         private void readEnforcingAdminAndSizeInner(TypedXmlPullParser parser)
2177                 throws XmlPullParserException, IOException {
2178             int outerDepth = parser.getDepth();
2179             EnforcingAdmin admin = null;
2180             int size = 0;
2181             while (XmlUtils.nextElementWithin(parser, outerDepth)) {
2182                 String tag = parser.getName();
2183                 switch (tag) {
2184                     case TAG_ENFORCING_ADMIN:
2185                         admin = EnforcingAdmin.readFromXml(parser);
2186                         break;
2187                     case TAG_POLICY_SUM_SIZE:
2188                         size = parser.getAttributeInt(/* namespace= */ null, ATTR_POLICY_SUM_SIZE);
2189                         break;
2190                     default:
2191                         Slogf.wtf(TAG, "Unknown tag " + tag);
2192                 }
2193             }
2194             if (admin == null) {
2195                 Slogf.wtf(TAG, "Error parsing enforcingAdmins, EnforcingAdmin is null.");
2196                 return;
2197             }
2198             if (size <= 0) {
2199                 Slogf.wtf(TAG, "Error parsing policy size, size is " + size);
2200                 return;
2201             }
2202             if (!mAdminPolicySize.contains(admin.getUserId())) {
2203                 mAdminPolicySize.put(admin.getUserId(), new HashMap<>());
2204             }
2205             mAdminPolicySize.get(admin.getUserId()).put(admin, size);
2206         }
2207 
readMaxPolicySizeInner(TypedXmlPullParser parser)2208         private void readMaxPolicySizeInner(TypedXmlPullParser parser)
2209                 throws XmlPullParserException, IOException {
2210             if (!Flags.devicePolicySizeTrackingInternalBugFixEnabled()) {
2211                 return;
2212             }
2213             mPolicySizeLimit = parser.getAttributeInt(/* namespace= */ null, ATTR_POLICY_SUM_SIZE);
2214         }
2215     }
2216 }
2217