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