1 /* 2 * Copyright (C) 2023 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.settings.testutils.shadow; 18 19 import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT; 20 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 21 import static android.os.Build.VERSION_CODES.O; 22 import static android.os.Build.VERSION_CODES.Q; 23 24 import android.annotation.UserIdInt; 25 import android.app.admin.DevicePolicyManager; 26 import android.app.admin.DevicePolicyManager.DeviceOwnerType; 27 import android.app.admin.IDevicePolicyManager; 28 import android.app.admin.ManagedSubscriptionsPolicy; 29 import android.app.admin.PasswordMetrics; 30 import android.app.admin.PasswordPolicy; 31 import android.content.ComponentName; 32 import android.content.Context; 33 34 import androidx.annotation.NonNull; 35 import androidx.annotation.Nullable; 36 import androidx.test.core.app.ApplicationProvider; 37 38 import org.robolectric.annotation.Implementation; 39 import org.robolectric.annotation.Implements; 40 import org.robolectric.shadow.api.Shadow; 41 42 import java.util.Collections; 43 import java.util.HashMap; 44 import java.util.List; 45 import java.util.Map; 46 import java.util.Objects; 47 import java.util.Set; 48 49 @Implements(DevicePolicyManager.class) 50 public class ShadowDevicePolicyManager extends org.robolectric.shadows.ShadowDevicePolicyManager { 51 52 private final Map<Integer, Long> mProfileTimeouts = new HashMap<>(); 53 private final Map<String, Integer> mDeviceOwnerTypes = new HashMap<>(); 54 private Map<Integer, CharSequence> mSupportMessagesMap = new HashMap<>(); 55 private boolean mIsAdminActiveAsUser = false; 56 private ComponentName mProfileOwner; 57 private ComponentName mDeviceOwnerComponentName; 58 private ManagedSubscriptionsPolicy mManagedSubscriptionsPolicy; 59 private int mDeviceOwnerUserId = -1; 60 private int mPasswordMinQuality = PASSWORD_QUALITY_UNSPECIFIED; 61 private int mPasswordMinLength = 0; 62 private int mPasswordMinSymbols = 0; 63 private Set<String> mCrossProfileCalendarPackages = Collections.emptySet(); 64 65 private List<String> mPermittedAccessibilityServices = null; 66 67 @Implementation(minSdk = O) __constructor__(Context context, IDevicePolicyManager service)68 protected void __constructor__(Context context, IDevicePolicyManager service) { 69 super.__constructor__(ApplicationProvider.getApplicationContext(), service); 70 } 71 setShortSupportMessageForUser(ComponentName admin, int userHandle, String message)72 public void setShortSupportMessageForUser(ComponentName admin, int userHandle, String message) { 73 mSupportMessagesMap.put(Objects.hash(admin, userHandle), message); 74 } 75 76 @Implementation getShortSupportMessageForUser(@onNull ComponentName admin, int userHandle)77 protected @Nullable CharSequence getShortSupportMessageForUser(@NonNull ComponentName admin, 78 int userHandle) { 79 return mSupportMessagesMap.get(Objects.hash(admin, userHandle)); 80 } 81 82 @Implementation isAdminActiveAsUser(@onNull ComponentName admin, int userId)83 protected boolean isAdminActiveAsUser(@NonNull ComponentName admin, int userId) { 84 return mIsAdminActiveAsUser; 85 } 86 87 @Implementation getDeviceOwnerUserId()88 protected int getDeviceOwnerUserId() { 89 return mDeviceOwnerUserId; 90 } 91 92 @Implementation getMaximumTimeToLock(ComponentName admin, @UserIdInt int userHandle)93 protected long getMaximumTimeToLock(ComponentName admin, @UserIdInt int userHandle) { 94 return mProfileTimeouts.getOrDefault(userHandle, 0L); 95 } 96 97 @Implementation getDeviceOwnerComponentOnAnyUser()98 protected ComponentName getDeviceOwnerComponentOnAnyUser() { 99 return mDeviceOwnerComponentName; 100 } 101 setIsAdminActiveAsUser(boolean active)102 public void setIsAdminActiveAsUser(boolean active) { 103 mIsAdminActiveAsUser = active; 104 } 105 setDeviceOwnerUserId(int id)106 public void setDeviceOwnerUserId(int id) { 107 mDeviceOwnerUserId = id; 108 } 109 setMaximumTimeToLock(@serIdInt int userHandle, Long timeout)110 public void setMaximumTimeToLock(@UserIdInt int userHandle, Long timeout) { 111 mProfileTimeouts.put(userHandle, timeout); 112 } 113 setDeviceOwnerComponentOnAnyUser(ComponentName admin)114 public void setDeviceOwnerComponentOnAnyUser(ComponentName admin) { 115 mDeviceOwnerComponentName = admin; 116 } 117 setDeviceOwnerType(@onNull ComponentName admin, @DeviceOwnerType int deviceOwnerType)118 public void setDeviceOwnerType(@NonNull ComponentName admin, 119 @DeviceOwnerType int deviceOwnerType) { 120 mDeviceOwnerTypes.put(admin.getPackageName(), deviceOwnerType); 121 } 122 setManagedSubscriptionsPolicy(ManagedSubscriptionsPolicy policy)123 public void setManagedSubscriptionsPolicy(ManagedSubscriptionsPolicy policy) { 124 mManagedSubscriptionsPolicy = policy; 125 } 126 127 @DeviceOwnerType getDeviceOwnerType(@onNull ComponentName admin)128 public int getDeviceOwnerType(@NonNull ComponentName admin) { 129 return mDeviceOwnerTypes.getOrDefault(admin.getPackageName(), DEVICE_OWNER_TYPE_DEFAULT); 130 } 131 132 @Implementation getPasswordMinimumMetrics(int userHandle)133 public PasswordMetrics getPasswordMinimumMetrics(int userHandle) { 134 PasswordPolicy policy = new PasswordPolicy(); 135 policy.quality = mPasswordMinQuality; 136 policy.length = mPasswordMinLength; 137 policy.symbols = mPasswordMinSymbols; 138 return policy.getMinMetrics(); 139 } 140 141 @Implementation getManagedSubscriptionsPolicy()142 public ManagedSubscriptionsPolicy getManagedSubscriptionsPolicy() { 143 return mManagedSubscriptionsPolicy; 144 } 145 setPasswordQuality(int quality)146 public void setPasswordQuality(int quality) { 147 mPasswordMinQuality = quality; 148 } 149 setPasswordMinimumLength(int length)150 public void setPasswordMinimumLength(int length) { 151 mPasswordMinLength = length; 152 } 153 setPasswordMinimumSymbols(int numOfSymbols)154 public void setPasswordMinimumSymbols(int numOfSymbols) { 155 mPasswordMinSymbols = numOfSymbols; 156 } 157 setPermittedAccessibilityServices(List<String> permittedAccessibilityServices)158 public void setPermittedAccessibilityServices(List<String> permittedAccessibilityServices) { 159 mPermittedAccessibilityServices = permittedAccessibilityServices; 160 } 161 162 @Implementation 163 @Nullable getPermittedAccessibilityServices(int userId)164 public List<String> getPermittedAccessibilityServices(int userId) { 165 return mPermittedAccessibilityServices; 166 } 167 getShadow()168 public static ShadowDevicePolicyManager getShadow() { 169 return (ShadowDevicePolicyManager) Shadow.extract( 170 ApplicationProvider.getApplicationContext() 171 .getSystemService(DevicePolicyManager.class)); 172 } 173 174 // BEGIN-INTERNAL 175 @Implementation(minSdk = Q) getCrossProfileCalendarPackages()176 protected Set<String> getCrossProfileCalendarPackages() { 177 return mCrossProfileCalendarPackages; 178 } 179 180 @Implementation(minSdk = Q) setCrossProfileCalendarPackages(ComponentName admin, Set<String> packageNames)181 public void setCrossProfileCalendarPackages(ComponentName admin, Set<String> packageNames) { 182 enforceProfileOwner(admin); 183 mCrossProfileCalendarPackages = packageNames; 184 } 185 186 /** 187 * Sets the admin as active admin and profile owner. 188 * 189 * @see DevicePolicyManager#getProfileOwner() 190 */ setProfileOwner(ComponentName admin)191 public void setProfileOwner(ComponentName admin) { 192 setActiveAdmin(admin); 193 mProfileOwner = admin; 194 } 195 enforceProfileOwner(ComponentName admin)196 private void enforceProfileOwner(ComponentName admin) { 197 if (!admin.equals(mProfileOwner)) { 198 throw new SecurityException("[" + admin + "] is not a profile owner"); 199 } 200 } 201 } 202