1 /*
2  * Copyright (C) 2018 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 package com.android.server.devicepolicy;
17 
18 import static android.app.admin.DevicePolicyManager.CONTENT_PROTECTION_DISABLED;
19 import static android.app.admin.DevicePolicyManager.ContentProtectionPolicy;
20 
21 import android.annotation.Nullable;
22 import android.annotation.UserIdInt;
23 import android.app.admin.DevicePolicyCache;
24 import android.app.admin.DevicePolicyManager;
25 import android.os.UserHandle;
26 import android.util.ArrayMap;
27 import android.util.IndentingPrintWriter;
28 import android.util.SparseIntArray;
29 
30 import com.android.internal.annotations.GuardedBy;
31 
32 import java.util.HashSet;
33 import java.util.Map;
34 import java.util.Set;
35 
36 /**
37  * Implementation of {@link DevicePolicyCache}, to which {@link DevicePolicyManagerService} pushes
38  * policies.
39  *
40  * TODO Move other copies of policies into this class too.
41  */
42 public class DevicePolicyCacheImpl extends DevicePolicyCache {
43     /**
44      * Lock object. For simplicity we just always use this as the lock. We could use each object
45      * as a lock object to make it more fine-grained, but that'd make copy-paste error-prone.
46      */
47     private final Object mLock = new Object();
48 
49     /**
50      * Indicates if screen capture is disallowed on a specific user or all users if
51      * it contains {@link UserHandle#USER_ALL}.
52      */
53     @GuardedBy("mLock")
54     private final Set<Integer> mScreenCaptureDisallowedUsers = new HashSet<>();
55 
56     @GuardedBy("mLock")
57     private final SparseIntArray mPasswordQuality = new SparseIntArray();
58 
59     @GuardedBy("mLock")
60     private final SparseIntArray mPermissionPolicy = new SparseIntArray();
61 
62     @GuardedBy("mLock")
63     private ArrayMap<String, String> mLauncherShortcutOverrides = new ArrayMap<>();
64 
65     /** Maps to {@code ActiveAdmin.mAdminCanGrantSensorsPermissions}. */
66     private volatile boolean mCanGrantSensorsPermissions = false;
67 
68     @GuardedBy("mLock")
69     private final SparseIntArray mContentProtectionPolicy = new SparseIntArray();
70 
onUserRemoved(int userHandle)71     public void onUserRemoved(int userHandle) {
72         synchronized (mLock) {
73             mPasswordQuality.delete(userHandle);
74             mPermissionPolicy.delete(userHandle);
75             mContentProtectionPolicy.delete(userHandle);
76         }
77     }
78 
79     @Override
isScreenCaptureAllowed(int userHandle)80     public boolean isScreenCaptureAllowed(int userHandle) {
81         // This won't work if resolution mechanism is not strictest applies, but it's ok for now.
82         synchronized (mLock) {
83             return !mScreenCaptureDisallowedUsers.contains(userHandle)
84                     && !mScreenCaptureDisallowedUsers.contains(UserHandle.USER_ALL);
85         }
86     }
87 
setScreenCaptureDisallowedUser(int userHandle, boolean disallowed)88     public void setScreenCaptureDisallowedUser(int userHandle, boolean disallowed) {
89         synchronized (mLock) {
90             if (disallowed) {
91                 mScreenCaptureDisallowedUsers.add(userHandle);
92             } else {
93                 mScreenCaptureDisallowedUsers.remove(userHandle);
94             }
95         }
96     }
97 
98     @Override
getPasswordQuality(@serIdInt int userHandle)99     public int getPasswordQuality(@UserIdInt int userHandle) {
100         synchronized (mLock) {
101             return mPasswordQuality.get(userHandle,
102                     DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
103         }
104     }
105 
106     /** Updat the password quality cache for the given user */
setPasswordQuality(int userHandle, int quality)107     public void setPasswordQuality(int userHandle, int quality) {
108         synchronized (mLock) {
109             mPasswordQuality.put(userHandle, quality);
110         }
111     }
112 
113     @Override
getPermissionPolicy(@serIdInt int userHandle)114     public int getPermissionPolicy(@UserIdInt int userHandle) {
115         synchronized (mLock) {
116             return mPermissionPolicy.get(userHandle,
117                     DevicePolicyManager.PERMISSION_POLICY_PROMPT);
118         }
119     }
120 
121     /** Update the permission policy for the given user. */
setPermissionPolicy(@serIdInt int userHandle, int policy)122     public void setPermissionPolicy(@UserIdInt int userHandle, int policy) {
123         synchronized (mLock) {
124             mPermissionPolicy.put(userHandle, policy);
125         }
126     }
127 
128     @Override
getContentProtectionPolicy(@serIdInt int userId)129     public @ContentProtectionPolicy int getContentProtectionPolicy(@UserIdInt int userId) {
130         synchronized (mLock) {
131             return mContentProtectionPolicy.get(userId, CONTENT_PROTECTION_DISABLED);
132         }
133     }
134 
135     /** Update the content protection policy for the given user. */
setContentProtectionPolicy(@serIdInt int userId, @Nullable Integer value)136     public void setContentProtectionPolicy(@UserIdInt int userId, @Nullable Integer value) {
137         synchronized (mLock) {
138             if (value == null) {
139                 mContentProtectionPolicy.delete(userId);
140             } else {
141                 mContentProtectionPolicy.put(userId, value);
142             }
143         }
144     }
145 
146     @Override
canAdminGrantSensorsPermissions()147     public boolean canAdminGrantSensorsPermissions() {
148         return mCanGrantSensorsPermissions;
149     }
150 
151     /** Sets admin control over permission grants. */
setAdminCanGrantSensorsPermissions(boolean canGrant)152     public void setAdminCanGrantSensorsPermissions(boolean canGrant) {
153         mCanGrantSensorsPermissions = canGrant;
154     }
155 
156     @Override
getLauncherShortcutOverrides()157     public Map<String, String> getLauncherShortcutOverrides() {
158         synchronized (mLock) {
159             return new ArrayMap<>(mLauncherShortcutOverrides);
160         }
161     }
162 
163     /**
164      * Sets a map of packages names to package names, for which all launcher shortcuts which
165      * match a key package name should be modified to launch the corresponding value package
166      * name in the managed profile. The overridden shortcut should be badged accordingly.
167      */
setLauncherShortcutOverrides(ArrayMap<String, String> launcherShortcutOverrides)168     public void setLauncherShortcutOverrides(ArrayMap<String, String> launcherShortcutOverrides) {
169         synchronized (mLock) {
170             mLauncherShortcutOverrides = new ArrayMap<>(launcherShortcutOverrides);
171         }
172     }
173 
174     /** Dump content */
dump(IndentingPrintWriter pw)175     public void dump(IndentingPrintWriter pw) {
176         synchronized (mLock) {
177             pw.println("Device policy cache:");
178             pw.increaseIndent();
179             pw.println("Screen capture disallowed users: " + mScreenCaptureDisallowedUsers);
180             pw.println("Password quality: " + mPasswordQuality);
181             pw.println("Permission policy: " + mPermissionPolicy);
182             pw.println("Content protection policy: " + mContentProtectionPolicy);
183             pw.println("Admin can grant sensors permission: " + mCanGrantSensorsPermissions);
184             pw.print("Shortcuts overrides: ");
185             pw.println(mLauncherShortcutOverrides);
186             pw.decreaseIndent();
187         }
188     }
189 }
190