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 17 package com.android.tv.settings.library.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.UserHandle; 25 import android.os.UserManager; 26 import android.provider.Settings; 27 28 import androidx.annotation.Nullable; 29 30 import java.util.Objects; 31 32 /** 33 * Utility class to host methods usable in adding a restricted padlock icon and showing admin 34 * support message dialog. 35 */ 36 public class RestrictedLockUtils { getProfileOrDeviceOwner( Context context, UserHandle user)37 public static EnforcedAdmin getProfileOrDeviceOwner( 38 Context context, UserHandle user) { 39 return getProfileOrDeviceOwner(context, null, user); 40 } 41 getProfileOrDeviceOwner( Context context, String enforcedRestriction, UserHandle user)42 public static RestrictedLockUtils.EnforcedAdmin getProfileOrDeviceOwner( 43 Context context, String enforcedRestriction, UserHandle user) { 44 if (user == null) { 45 return null; 46 } 47 final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 48 if (dpm == null) { 49 return null; 50 } 51 52 Context userContext; 53 try { 54 userContext = context.createPackageContextAsUser(context.getPackageName(), 0, user); 55 } catch (PackageManager.NameNotFoundException e) { 56 throw new IllegalStateException(e); 57 } 58 59 ComponentName adminComponent = userContext.getSystemService( 60 DevicePolicyManager.class).getProfileOwner(); 61 if (adminComponent != null) { 62 return new EnforcedAdmin(adminComponent, enforcedRestriction, user); 63 } 64 if (Objects.equals(dpm.getDeviceOwnerUser(), user)) { 65 adminComponent = dpm.getDeviceOwnerComponentOnAnyUser(); 66 if (adminComponent != null) { 67 return new EnforcedAdmin(adminComponent, enforcedRestriction, user); 68 } 69 } 70 return null; 71 } 72 73 /** 74 * Send the intent to trigger the {@code android.settings.ShowAdminSupportDetailsDialog}. 75 */ sendShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin)76 public static void sendShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin) { 77 final Intent intent = getShowAdminSupportDetailsIntent(context, admin); 78 int targetUserId = UserHandle.myUserId(); 79 if (admin != null) { 80 if (admin.user != null 81 && isCurrentUserOrProfile(context, admin.user.getIdentifier())) { 82 targetUserId = admin.user.getIdentifier(); 83 } 84 intent.putExtra(DevicePolicyManager.EXTRA_RESTRICTION, admin.enforcedRestriction); 85 } 86 context.startActivityAsUser(intent, UserHandle.of(targetUserId)); 87 } 88 getShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin)89 public static Intent getShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin) { 90 final Intent intent = new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS); 91 if (admin != null) { 92 if (admin.component != null) { 93 intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin.component); 94 } 95 intent.putExtra(Intent.EXTRA_USER, admin.user); 96 } 97 return intent; 98 } 99 isCurrentUserOrProfile(Context context, int userId)100 public static boolean isCurrentUserOrProfile(Context context, int userId) { 101 UserManager um = context.getSystemService(UserManager.class); 102 return um.getUserProfiles().contains(UserHandle.of(userId)); 103 } 104 105 public static class EnforcedAdmin { 106 @Nullable 107 public ComponentName component = null; 108 /** 109 * The restriction enforced by admin. It could be any user restriction or policy like 110 * {@link DevicePolicyManager#POLICY_DISABLE_CAMERA}. 111 */ 112 @Nullable 113 public String enforcedRestriction = null; 114 @Nullable 115 public UserHandle user = null; 116 117 // We use this to represent the case where a policy is enforced by multiple admins. 118 public final static RestrictedLockUtils.EnforcedAdmin MULTIPLE_ENFORCED_ADMIN = 119 new EnforcedAdmin(); 120 createDefaultEnforcedAdminWithRestriction( String enforcedRestriction)121 public static EnforcedAdmin createDefaultEnforcedAdminWithRestriction( 122 String enforcedRestriction) { 123 EnforcedAdmin enforcedAdmin = new RestrictedLockUtils.EnforcedAdmin(); 124 enforcedAdmin.enforcedRestriction = enforcedRestriction; 125 return enforcedAdmin; 126 } 127 EnforcedAdmin(ComponentName component, UserHandle user)128 public EnforcedAdmin(ComponentName component, UserHandle user) { 129 this.component = component; 130 this.user = user; 131 } 132 EnforcedAdmin(ComponentName component, String enforcedRestriction, UserHandle user)133 public EnforcedAdmin(ComponentName component, String enforcedRestriction, UserHandle user) { 134 this.component = component; 135 this.enforcedRestriction = enforcedRestriction; 136 this.user = user; 137 } 138 EnforcedAdmin(EnforcedAdmin other)139 public EnforcedAdmin(EnforcedAdmin other) { 140 if (other == null) { 141 throw new IllegalArgumentException(); 142 } 143 this.component = other.component; 144 this.enforcedRestriction = other.enforcedRestriction; 145 this.user = other.user; 146 } 147 EnforcedAdmin()148 public EnforcedAdmin() { 149 } 150 151 /** 152 * Combines two {@link EnforcedAdmin} into one: if one of them is null, then just return 153 * the other. If both of them are the same, then return that. Otherwise return the symbolic 154 * {@link #MULTIPLE_ENFORCED_ADMIN} 155 */ combine(EnforcedAdmin admin1, EnforcedAdmin admin2)156 public static EnforcedAdmin combine(EnforcedAdmin admin1, EnforcedAdmin admin2) { 157 if (admin1 == null) { 158 return admin2; 159 } 160 if (admin2 == null) { 161 return admin1; 162 } 163 if (admin1.equals(admin2)) { 164 return admin1; 165 } 166 if (!admin1.enforcedRestriction.equals(admin2.enforcedRestriction)) { 167 throw new IllegalArgumentException( 168 "Admins with different restriction cannot be combined"); 169 } 170 return MULTIPLE_ENFORCED_ADMIN; 171 } 172 173 @Override equals(Object o)174 public boolean equals(Object o) { 175 if (this == o) return true; 176 if (o == null || getClass() != o.getClass()) return false; 177 EnforcedAdmin that = (EnforcedAdmin) o; 178 return Objects.equals(user, that.user) && 179 Objects.equals(component, that.component) && 180 Objects.equals(enforcedRestriction, that.enforcedRestriction); 181 } 182 183 @Override hashCode()184 public int hashCode() { 185 return Objects.hash(component, enforcedRestriction, user); 186 } 187 188 @Override toString()189 public String toString() { 190 return "EnforcedAdmin{" + 191 "component=" + component + 192 ", enforcedRestriction='" + enforcedRestriction + 193 ", user=" + user + 194 '}'; 195 } 196 } 197 } 198 199