• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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.car.settings.enterprise;
17 
18 import android.Manifest;
19 import android.annotation.Nullable;
20 import android.annotation.UserIdInt;
21 import android.app.admin.DeviceAdminInfo;
22 import android.app.admin.DevicePolicyManager;
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.pm.ActivityInfo;
27 import android.content.pm.PackageManager;
28 import android.os.Bundle;
29 import android.os.UserHandle;
30 import android.os.UserManager;
31 
32 import com.android.car.settings.common.Logger;
33 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
34 import com.android.settingslib.RestrictedLockUtilsInternal;
35 
36 import org.xmlpull.v1.XmlPullParserException;
37 
38 import java.io.IOException;
39 import java.util.List;
40 
41 /**
42  * Generic helper methods for this package.
43  */
44 public final class EnterpriseUtils {
45 
46     private static final Logger LOG = new Logger(EnterpriseUtils.class);
47     // TODO: ideally, we should not create a special user restriction other than what are
48     // defined in UserManager.
49     public static final String DISABLED_INPUT_METHOD = "disabled-input-method";
50     // TODO: same as for DISABLED_INPUT_METHOD
51     public static final String BLOCKED_UNINSTALL_APP = "blocked-uninstall-app";
52 
53     static final String[] CAMERA_PERMISSIONS = new String[] {
54             Manifest.permission.CAMERA
55     };
56     static final String[] LOCATION_PERMISSIONS = new String[] {
57             Manifest.permission.ACCESS_COARSE_LOCATION,
58             Manifest.permission.ACCESS_FINE_LOCATION
59     };
60     static final String[] MICROPHONE_PERMISSIONS = new String[] {
61             Manifest.permission.RECORD_AUDIO
62     };
63 
64     /**
65      * Gets the active admin for the given package.
66      */
67     @Nullable
getAdminWithinPackage(Context context, String packageName)68     public static ComponentName getAdminWithinPackage(Context context, String packageName) {
69         List<ComponentName> admins = context.getSystemService(DevicePolicyManager.class)
70                 .getActiveAdmins();
71         if (admins == null) {
72             LOG.v("getAdminWithinPackage(): no active admins on context");
73             return null;
74         }
75         return admins.stream().filter(i -> i.getPackageName().equals(packageName)).findAny()
76                 .orElse(null);
77     }
78 
79     /**
80      * Gets the active admin info for the given admin .
81      */
82     @Nullable
getDeviceAdminInfo(Context context, ComponentName admin)83     public static DeviceAdminInfo getDeviceAdminInfo(Context context, ComponentName admin) {
84         LOG.d("getDeviceAdminInfo()(): " + admin.flattenToShortString());
85 
86         ActivityInfo ai;
87         try {
88             ai = context.getPackageManager().getReceiverInfo(admin, PackageManager.GET_META_DATA);
89         } catch (PackageManager.NameNotFoundException e) {
90             LOG.v("Unable to get activity info for " + admin.flattenToShortString() + ": " + e);
91             return null;
92         }
93 
94         try {
95             return new DeviceAdminInfo(context, ai);
96         } catch (XmlPullParserException | IOException e) {
97             LOG.v("Unable to retrieve device policy for " + admin.flattenToShortString() + ": ",
98                     e);
99             return null;
100         }
101     }
102 
103     /**
104      * Checks whether current user has the flag {@link UserManager.FLAG_DEMO}.
105      */
isDemoUser(Context context)106     public static boolean isDemoUser(Context context) {
107         return UserManager.isDeviceInDemoMode(context)
108                 && getUserManager(context).isDemoUser();
109     }
110 
111     /**
112      * Checks whether current user has the flag {@link UserManager.FLAG_ADMIN}.
113      */
isAdminUser(Context context)114     public static boolean isAdminUser(Context context) {
115         return getUserManager(context).isAdminUser();
116     }
117 
118     /**
119      * Checks whether the restriction is set on the current user by device owner / profile owners
120      * but not by {@link UserManager}.
121      *
122      * <p>This includes restriction set on device owner but current user has affiliated profile
123      * owner.
124      */
hasUserRestrictionByDpm(Context context, String restriction)125     public static boolean hasUserRestrictionByDpm(Context context, String restriction) {
126         if (hasUserRestrictionByUm(context, restriction)) {
127             return false;
128         }
129         return getUserManager(context).hasUserRestriction(restriction);
130     }
131 
132     /**
133      * Checks whether there are restrictions set via {@link UserManager} which doesn't include
134      * restrictions set by device owner / profile owners.
135      */
hasUserRestrictionByUm(Context context, String restriction)136     public static boolean hasUserRestrictionByUm(Context context, String restriction) {
137         return getUserManager(context)
138                 .hasBaseUserRestriction(restriction, UserHandle.of(context.getUserId()));
139     }
140 
141     /**
142      * Checks whether the device is managed.
143      */
isDeviceManaged(Context context)144     public static boolean isDeviceManaged(Context context) {
145         DevicePolicyManager dpm = getDevicePolicyManager(context);
146         return dpm.isDeviceManaged();
147     }
148 
149     /**
150      * Checks whether device owner is set on the device.
151      */
hasDeviceOwner(Context context)152     public static boolean hasDeviceOwner(Context context) {
153         DevicePolicyManager dpm = getDevicePolicyManager(context);
154         return dpm.isDeviceManaged() && getDeviceOwner(context) != null;
155     }
156 
157     /**
158      * Gets device owner user id on the device.
159      */
160     @UserIdInt
getDeviceOwnerUserId(Context context)161     private static int getDeviceOwnerUserId(Context context) {
162         return getDevicePolicyManager(context).getDeviceOwnerUserId();
163     }
164 
165     /**
166      * Gets device owner component on the device.
167      */
168     @Nullable
getDeviceOwner(Context context)169     private static ComponentName getDeviceOwner(Context context) {
170         return getDevicePolicyManager(context).getDeviceOwnerComponentOnAnyUser();
171     }
172 
getUserManager(Context context)173     private static UserManager getUserManager(Context context) {
174         return context.getSystemService(UserManager.class);
175     }
176 
getDevicePolicyManager(Context context)177     private static DevicePolicyManager getDevicePolicyManager(Context context) {
178         return context.getSystemService(DevicePolicyManager.class);
179     }
180 
181     /**
182      * Gets an {@code ActionDisabledByAdminDialogFragment} for the target restriction to show on
183      * the current user.
184      */
getActionDisabledByAdminDialog( Context context, String restriction)185     public static ActionDisabledByAdminDialogFragment getActionDisabledByAdminDialog(
186             Context context, String restriction) {
187         return getActionDisabledByAdminDialog(context, restriction, /* restrictedPackage= */ null);
188     }
189 
190     /**
191      * Gets an {@code ActionDisabledByAdminDialogFragment} when the input method is restricted for
192      * the current user.
193      */
getInputMethodDisabledByAdminDialog( Context context, String restriction)194     public static ActionDisabledByAdminDialogFragment getInputMethodDisabledByAdminDialog(
195             Context context, String restriction) {
196         return getActionDisabledByAdminDialog(context, restriction, /* restrictedPackage= */ null);
197     }
198 
199     /**
200      * Gets an {@code ActionDisabledByAdminDialogFragment} for the target restriction to show on
201      * the current user with additional restricted package information.
202      */
getActionDisabledByAdminDialog( Context context, String restriction, @Nullable String restrictedPackage)203     public static ActionDisabledByAdminDialogFragment getActionDisabledByAdminDialog(
204             Context context, String restriction, @Nullable String restrictedPackage) {
205         int adminUser = hasDeviceOwner(context)
206                 ? getDeviceOwnerUserId(context)
207                 : context.getUserId();
208         return ActionDisabledByAdminDialogFragment
209                 .newInstance(restriction, restrictedPackage, adminUser);
210     }
211 
212     /**
213      * Gets enforced admin information from Intent that started the
214      * {@code ActionDisabledByAdminDialogActivity}.
215      */
getEnforcedAdminFromIntent(Context context, Intent intent)216     public static EnforcedAdmin getEnforcedAdminFromIntent(Context context, Intent intent) {
217         EnforcedAdmin admin = new EnforcedAdmin(null, context.getUser());
218         if (intent == null) {
219             return admin;
220         }
221         admin.component = intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN);
222         int userId = intent.getIntExtra(Intent.EXTRA_USER_ID, context.getUserId());
223 
224         Bundle adminDetails = null;
225         if (admin.component == null) {
226             DevicePolicyManager devicePolicyManager = getDevicePolicyManager(context);
227             admin.component = adminDetails.getParcelable(DevicePolicyManager.EXTRA_DEVICE_ADMIN);
228         }
229 
230         if (intent.hasExtra(Intent.EXTRA_USER)) {
231             admin.user = intent.getParcelableExtra(Intent.EXTRA_USER);
232         } else {
233             if (adminDetails != null) {
234                 userId = adminDetails.getInt(Intent.EXTRA_USER_ID, UserHandle.myUserId());
235             }
236             if (userId == UserHandle.USER_NULL) {
237                 admin.user = null;
238             } else {
239                 admin.user = UserHandle.of(userId);
240             }
241         }
242         return admin;
243     }
244 
245     /**
246      * Gets {@code RestrictedLockUtils.EnforcedAdmin} for the device policy that affects
247      * current user.
248      *
249      * @param context for current user
250      * @param adminUser which can be either profile owner on current user or device owner on
251      *        headless system user
252      * @param restriction which can be user restriction or restriction policy defined
253      *        in this class
254      * @param restrictedPackage is the target package that restriction policy is set
255      * @return {@code RestrictedLockUtils.EnforcedAdmin}
256      */
getEnforcedAdmin(Context context, @UserIdInt int adminUser, @Nullable String restriction, String restrictedPackage)257     public static EnforcedAdmin getEnforcedAdmin(Context context, @UserIdInt int adminUser,
258             @Nullable String restriction, String restrictedPackage) {
259         if (restriction == null) {
260             return null;
261         }
262         EnforcedAdmin admin = null;
263         if (hasUserRestrictionByDpm(context, restriction)) {
264             admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
265                     context, restriction, context.getUserId());
266             LOG.v("getEnforcedAdmin(): " + adminUser + " restriction: " + restriction
267                     + " restrictedPackage: " + restrictedPackage);
268 
269             if (admin.component == null && context.getUserId() != adminUser) {
270                 // User restriction might be set on primary user which is user 0 as a device-wide
271                 // policy.
272                 admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
273                         context, restriction, adminUser);
274             }
275         } else if (restriction.equals(DISABLED_INPUT_METHOD)) {
276             if (restrictedPackage == null) {
277                 LOG.e("getEnforcedAdmin() for " + DISABLED_INPUT_METHOD
278                         + " fails since restrictedPackage is null");
279                 return admin;
280             }
281             admin = RestrictedLockUtilsInternal.checkIfInputMethodDisallowed(
282                     context, restrictedPackage, context.getUserId());
283         } else if (restriction.equals(BLOCKED_UNINSTALL_APP)) {
284             admin = RestrictedLockUtilsInternal.checkIfUninstallBlocked(
285                     context, restrictedPackage, context.getUserId());
286         }
287         LOG.v("getEnforcedAdmin():" + admin);
288         return admin;
289     }
290 
EnterpriseUtils()291     private EnterpriseUtils() {
292         throw new UnsupportedOperationException("Provides only static methods");
293     }
294 }
295