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 17 package com.android.settingslib; 18 19 import android.app.admin.DevicePolicyManager; 20 import android.content.ComponentName; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.pm.PackageManager; 24 import android.os.Build; 25 import android.os.UserHandle; 26 import android.os.UserManager; 27 import android.provider.Settings; 28 29 import androidx.annotation.Nullable; 30 import androidx.annotation.RequiresApi; 31 32 import java.util.Objects; 33 34 /** 35 * Utility class to host methods usable in adding a restricted padlock icon and showing admin 36 * support message dialog. 37 */ 38 public class RestrictedLockUtils { 39 /** 40 * Gets EnforcedAdmin from DevicePolicyManager 41 */ 42 @RequiresApi(Build.VERSION_CODES.M) getProfileOrDeviceOwner(Context context, UserHandle user)43 public static EnforcedAdmin getProfileOrDeviceOwner(Context context, UserHandle user) { 44 return getProfileOrDeviceOwner(context, null, user); 45 } 46 47 /** 48 * Gets EnforcedAdmin from DevicePolicyManager 49 */ 50 @RequiresApi(Build.VERSION_CODES.M) getProfileOrDeviceOwner( Context context, String enforcedRestriction, UserHandle user)51 public static EnforcedAdmin getProfileOrDeviceOwner( 52 Context context, String enforcedRestriction, UserHandle user) { 53 if (user == null) { 54 return null; 55 } 56 final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService( 57 Context.DEVICE_POLICY_SERVICE); 58 if (dpm == null) { 59 return null; 60 } 61 62 Context userContext; 63 try { 64 userContext = context.createPackageContextAsUser(context.getPackageName(), 0, user); 65 } catch (PackageManager.NameNotFoundException e) { 66 throw new IllegalStateException(e); 67 } 68 69 ComponentName adminComponent = userContext.getSystemService( 70 DevicePolicyManager.class).getProfileOwner(); 71 if (adminComponent != null) { 72 return new EnforcedAdmin(adminComponent, enforcedRestriction, user); 73 } 74 if (Objects.equals(dpm.getDeviceOwnerUser(), user)) { 75 adminComponent = dpm.getDeviceOwnerComponentOnAnyUser(); 76 if (adminComponent != null) { 77 return new EnforcedAdmin(adminComponent, enforcedRestriction, user); 78 } 79 } 80 return null; 81 } 82 83 /** 84 * Sends the intent to trigger the {@code android.settings.ShowAdminSupportDetailsDialog}. 85 */ 86 @RequiresApi(Build.VERSION_CODES.M) sendShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin)87 public static void sendShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin) { 88 final Intent intent = getShowAdminSupportDetailsIntent(admin); 89 int targetUserId = UserHandle.myUserId(); 90 if (admin != null) { 91 if (admin.user != null 92 && isCurrentUserOrProfile(context, admin.user.getIdentifier())) { 93 targetUserId = admin.user.getIdentifier(); 94 } 95 intent.putExtra(DevicePolicyManager.EXTRA_RESTRICTION, admin.enforcedRestriction); 96 } 97 context.startActivityAsUser(intent, UserHandle.of(targetUserId)); 98 } 99 100 /** 101 * @deprecated No context needed. Use {@link #getShowAdminSupportDetailsIntent(EnforcedAdmin)}. 102 */ getShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin)103 public static Intent getShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin) { 104 return getShowAdminSupportDetailsIntent(admin); 105 } 106 107 /** 108 * Gets the intent to trigger the {@code android.settings.ShowAdminSupportDetailsDialog}. 109 */ getShowAdminSupportDetailsIntent(EnforcedAdmin admin)110 public static Intent getShowAdminSupportDetailsIntent(EnforcedAdmin admin) { 111 final Intent intent = new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS); 112 if (admin != null) { 113 if (admin.component != null) { 114 intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin.component); 115 } 116 intent.putExtra(Intent.EXTRA_USER, admin.user); 117 } 118 return intent; 119 } 120 121 /** 122 * Checks if current user is profile or not 123 */ 124 @RequiresApi(Build.VERSION_CODES.M) isCurrentUserOrProfile(Context context, int userId)125 public static boolean isCurrentUserOrProfile(Context context, int userId) { 126 UserManager um = context.getSystemService(UserManager.class); 127 return um.getUserProfiles().contains(UserHandle.of(userId)); 128 } 129 130 /** 131 * A admin for the restriction enforced. 132 */ 133 public static class EnforcedAdmin { 134 @Nullable 135 public ComponentName component = null; 136 /** 137 * The restriction enforced by admin. It could be any user restriction or policy like 138 * {@link DevicePolicyManager#POLICY_DISABLE_CAMERA}. 139 */ 140 @Nullable 141 public String enforcedRestriction = null; 142 @Nullable 143 public UserHandle user = null; 144 145 /** 146 * We use this to represent the case where a policy is enforced by multiple admins. 147 */ 148 public static final EnforcedAdmin MULTIPLE_ENFORCED_ADMIN = new EnforcedAdmin(); 149 150 /** 151 * The restriction enforced by admin with restriction. 152 */ createDefaultEnforcedAdminWithRestriction( String enforcedRestriction)153 public static EnforcedAdmin createDefaultEnforcedAdminWithRestriction( 154 String enforcedRestriction) { 155 final EnforcedAdmin enforcedAdmin = new EnforcedAdmin(); 156 enforcedAdmin.enforcedRestriction = enforcedRestriction; 157 return enforcedAdmin; 158 } 159 EnforcedAdmin(ComponentName component, UserHandle user)160 public EnforcedAdmin(ComponentName component, UserHandle user) { 161 this.component = component; 162 this.user = user; 163 } 164 EnforcedAdmin(ComponentName component, String enforcedRestriction, UserHandle user)165 public EnforcedAdmin(ComponentName component, String enforcedRestriction, UserHandle user) { 166 this.component = component; 167 this.enforcedRestriction = enforcedRestriction; 168 this.user = user; 169 } 170 EnforcedAdmin(EnforcedAdmin other)171 public EnforcedAdmin(EnforcedAdmin other) { 172 if (other == null) { 173 throw new IllegalArgumentException(); 174 } 175 this.component = other.component; 176 this.enforcedRestriction = other.enforcedRestriction; 177 this.user = other.user; 178 } 179 EnforcedAdmin()180 public EnforcedAdmin() {} 181 182 /** 183 * Combines two {@link EnforcedAdmin} into one: if one of them is null, then just return 184 * the other. If both of them are the same, then return that. Otherwise return the symbolic 185 * {@link #MULTIPLE_ENFORCED_ADMIN} 186 */ combine(EnforcedAdmin admin1, EnforcedAdmin admin2)187 public static EnforcedAdmin combine(EnforcedAdmin admin1, EnforcedAdmin admin2) { 188 if (admin1 == null) { 189 return admin2; 190 } 191 if (admin2 == null) { 192 return admin1; 193 } 194 if (admin1.equals(admin2)) { 195 return admin1; 196 } 197 if (!admin1.enforcedRestriction.equals(admin2.enforcedRestriction)) { 198 throw new IllegalArgumentException( 199 "Admins with different restriction cannot be combined"); 200 } 201 return MULTIPLE_ENFORCED_ADMIN; 202 } 203 204 @Override equals(Object o)205 public boolean equals(Object o) { 206 if (this == o) return true; 207 if (o == null || getClass() != o.getClass()) return false; 208 EnforcedAdmin that = (EnforcedAdmin) o; 209 return Objects.equals(user, that.user) 210 && Objects.equals(component, that.component) 211 && Objects.equals(enforcedRestriction, that.enforcedRestriction); 212 } 213 214 @Override hashCode()215 public int hashCode() { 216 return Objects.hash(component, enforcedRestriction, user); 217 } 218 219 @Override toString()220 public String toString() { 221 return "EnforcedAdmin{" 222 + "component=" + component 223 + ", enforcedRestriction='" + enforcedRestriction 224 + ", user=" + user 225 + '}'; 226 } 227 } 228 229 /** 230 * Shows restricted setting dialog. 231 * 232 * @deprecated TODO(b/308921175): This will be deleted with the 233 * {@link android.security.Flags#extendEcmToAllSettings} feature flag. Do not use for any new 234 * code. 235 */ 236 @Deprecated 237 @RequiresApi(Build.VERSION_CODES.TIRAMISU) sendShowRestrictedSettingDialogIntent(Context context, String packageName, int uid)238 public static void sendShowRestrictedSettingDialogIntent(Context context, 239 String packageName, int uid) { 240 final Intent intent = getShowRestrictedSettingsIntent(packageName, uid); 241 context.startActivity(intent); 242 } 243 244 /** 245 * Gets restricted settings dialog intent. 246 * 247 * @deprecated TODO(b/308921175): This will be deleted with the 248 * {@link android.security.Flags#extendEcmToAllSettings} feature flag. Do not use for any new 249 * code. 250 */ 251 @Deprecated getShowRestrictedSettingsIntent(String packageName, int uid)252 private static Intent getShowRestrictedSettingsIntent(String packageName, int uid) { 253 final Intent intent = new Intent(Settings.ACTION_SHOW_RESTRICTED_SETTING_DIALOG); 254 intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); 255 intent.putExtra(Intent.EXTRA_UID, uid); 256 return intent; 257 } 258 } 259