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