1 package org.robolectric.shadows; 2 3 import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1; 4 import static android.os.Build.VERSION_CODES.M; 5 import static android.os.Build.VERSION_CODES.O; 6 import static android.os.Build.VERSION_CODES.O_MR1; 7 8 import android.app.Activity; 9 import android.app.KeyguardManager; 10 import android.app.KeyguardManager.KeyguardDismissCallback; 11 import android.content.Intent; 12 import java.util.HashSet; 13 import java.util.Set; 14 import org.robolectric.annotation.Implementation; 15 import org.robolectric.annotation.Implements; 16 import org.robolectric.annotation.Resetter; 17 18 @Implements(KeyguardManager.class) 19 public class ShadowKeyguardManager { 20 // These have to be static because on Android L and below, a new instance of KeyguardManager is 21 // created each time it is requested. 22 private static final Set<Integer> deviceLockedForUsers = new HashSet<Integer>(); 23 private static final Set<Integer> deviceSecureForUsers = new HashSet<Integer>(); 24 private static boolean inRestrictedInputMode; 25 private static boolean isKeyguardLocked; 26 private static boolean isDeviceLocked; 27 private static boolean isKeyguardSecure; 28 private static boolean isDeviceSecure; 29 private static Intent confirmFactoryResetCredentialIntent; 30 private static KeyguardManager.KeyguardDismissCallback callback; 31 32 /** 33 * For tests, returns the value set via {@link #setinRestrictedInputMode(boolean)}, or false by 34 * default. 35 * 36 * @see #setInRestrictedInputMode(boolean) 37 */ 38 @Implementation inKeyguardRestrictedInputMode()39 protected boolean inKeyguardRestrictedInputMode() { 40 return inRestrictedInputMode; 41 } 42 43 @Implementation(minSdk = O) requestDismissKeyguard( Activity activity, KeyguardManager.KeyguardDismissCallback callback)44 protected void requestDismissKeyguard( 45 Activity activity, KeyguardManager.KeyguardDismissCallback callback) { 46 if (isKeyguardLocked) { 47 if (ShadowKeyguardManager.callback != null) { 48 callback.onDismissError(); 49 } 50 ShadowKeyguardManager.callback = callback; 51 } else { 52 callback.onDismissError(); 53 } 54 } 55 56 /** 57 * For tests, returns the value set via {@link #setKeyguardLocked(boolean)}, or false by default. 58 * 59 * @see #setKeyguardLocked(boolean) 60 */ 61 @Implementation isKeyguardLocked()62 protected boolean isKeyguardLocked() { 63 return isKeyguardLocked; 64 } 65 66 /** 67 * Sets whether the device keyguard is locked or not. This affects the value to be returned by 68 * {@link #isKeyguardLocked()} and also invokes callbacks set in {@link 69 * KeyguardManager#requestDismissKeyguard(Activity, KeyguardDismissCallback)} ()}. 70 * 71 * @param isKeyguardLocked true to lock the keyguard. If a KeyguardDismissCallback is set will 72 * fire {@link KeyguardDismissCallback#onDismissCancelled()} or false to unlock and dismiss 73 * the keyguard firing {@link KeyguardDismissCallback#onDismissSucceeded()} if a 74 * KeyguardDismissCallback is set. 75 */ setKeyguardLocked(boolean isKeyguardLocked)76 public void setKeyguardLocked(boolean isKeyguardLocked) { 77 ShadowKeyguardManager.isKeyguardLocked = isKeyguardLocked; 78 if (callback != null) { 79 if (isKeyguardLocked) { 80 callback.onDismissCancelled(); 81 } else { 82 callback.onDismissSucceeded(); 83 } 84 callback = null; 85 } 86 } 87 88 /** 89 * Sets the value to be returned by {@link KeyguardManager#inKeyguardRestrictedInputMode()}. 90 * 91 * @see KeyguardManager#inKeyguardRestrictedInputMode() 92 * @deprecated use {@link #setInRestrictedInputMode(boolean)} instead 93 */ 94 @Deprecated setinRestrictedInputMode(boolean restricted)95 public void setinRestrictedInputMode(boolean restricted) { 96 inRestrictedInputMode = restricted; 97 } 98 99 /** 100 * Sets the value to be returned by {@link KeyguardManager#inKeyguardRestrictedInputMode()}. 101 * 102 * @see KeyguardManager#inKeyguardRestrictedInputMode() 103 */ setInRestrictedInputMode(boolean restricted)104 public void setInRestrictedInputMode(boolean restricted) { 105 inRestrictedInputMode = restricted; 106 } 107 108 /** 109 * For tests, returns the value set by {@link #setIsKeyguardSecure(boolean)}, or false by default. 110 * 111 * @see #setIsKeyguardSecure(boolean) 112 */ 113 @Implementation isKeyguardSecure()114 protected boolean isKeyguardSecure() { 115 return isKeyguardSecure; 116 } 117 118 /** 119 * Sets the value to be returned by {@link #isKeyguardSecure()}. 120 * 121 * @see #isKeyguardSecure() 122 */ setIsKeyguardSecure(boolean secure)123 public void setIsKeyguardSecure(boolean secure) { 124 isKeyguardSecure = secure; 125 } 126 127 /** 128 * For tests on Android >=M, returns the value set by {@link #setIsDeviceSecure(boolean)}, or 129 * false by default. 130 * 131 * @see #setIsDeviceSecure(boolean) 132 */ 133 @Implementation(minSdk = M) isDeviceSecure()134 protected boolean isDeviceSecure() { 135 return isDeviceSecure; 136 } 137 138 /** 139 * For tests on Android >=M, sets the value to be returned by {@link #isDeviceSecure()}. 140 * 141 * @see #isDeviceSecure() 142 */ setIsDeviceSecure(boolean isDeviceSecure)143 public void setIsDeviceSecure(boolean isDeviceSecure) { 144 ShadowKeyguardManager.isDeviceSecure = isDeviceSecure; 145 } 146 147 /** 148 * For tests on Android >=M, returns the value set by {@link #setIsDeviceSecure(int, boolean)}, or 149 * false by default. 150 * 151 * @see #setIsDeviceSecure(int, boolean) 152 */ 153 @Implementation(minSdk = M) isDeviceSecure(int userId)154 protected boolean isDeviceSecure(int userId) { 155 return deviceSecureForUsers.contains(userId); 156 } 157 158 /** 159 * For tests on Android >=M, sets the value to be returned by {@link #isDeviceSecure(int)}. 160 * 161 * @see #isDeviceSecure(int) 162 */ setIsDeviceSecure(int userId, boolean isDeviceSecure)163 public void setIsDeviceSecure(int userId, boolean isDeviceSecure) { 164 if (isDeviceSecure) { 165 deviceSecureForUsers.add(userId); 166 } else { 167 deviceSecureForUsers.remove(userId); 168 } 169 } 170 171 /** 172 * For tests on Android >=L MR1, sets the value to be returned by {@link #isDeviceLocked()}. 173 * 174 * @see #isDeviceLocked() 175 */ setIsDeviceLocked(boolean isDeviceLocked)176 public void setIsDeviceLocked(boolean isDeviceLocked) { 177 ShadowKeyguardManager.isDeviceLocked = isDeviceLocked; 178 } 179 180 /** 181 * @return false by default, or the value passed to {@link #setIsDeviceLocked(boolean)}. 182 * @see #isDeviceLocked() 183 */ 184 @Implementation(minSdk = LOLLIPOP_MR1) isDeviceLocked()185 protected boolean isDeviceLocked() { 186 return isDeviceLocked; 187 } 188 189 /** 190 * For tests on Android >= L MR1, sets the value to be returned by {@link #isDeviceLocked(int)}. 191 * 192 * @see #isDeviceLocked(int) 193 */ setIsDeviceLocked(int userId, boolean isLocked)194 public void setIsDeviceLocked(int userId, boolean isLocked) { 195 if (isLocked) { 196 deviceLockedForUsers.add(userId); 197 } else { 198 deviceLockedForUsers.remove(userId); 199 } 200 } 201 202 @Implementation(minSdk = LOLLIPOP_MR1) isDeviceLocked(int userId)203 protected boolean isDeviceLocked(int userId) { 204 return deviceLockedForUsers.contains(userId); 205 } 206 207 /** 208 * For tests on Android >= O MR1, sets the value to be returned by {@link 209 * #createConfirmFactoryResetCredentialIntent(CharSequence,CharSequence,CharSequence)}. 210 * 211 * @see #createConfirmFactoryResetCredentialIntent(CharSequence,CharSequence,CharSequence) 212 */ setConfirmFactoryResetCredentialIntent(Intent intent)213 public void setConfirmFactoryResetCredentialIntent(Intent intent) { 214 confirmFactoryResetCredentialIntent = intent; 215 } 216 217 /** 218 * Returns the intent set via {@link #setConfirmFactoryResetCredentialIntent(Intent)}, otherwise 219 * null. 220 */ 221 @Implementation(minSdk = O_MR1) createConfirmFactoryResetCredentialIntent( CharSequence title, CharSequence description, CharSequence alternateButtonLabel)222 protected Intent createConfirmFactoryResetCredentialIntent( 223 CharSequence title, CharSequence description, CharSequence alternateButtonLabel) { 224 return confirmFactoryResetCredentialIntent; 225 } 226 227 /** An implementation of {@link KeyguardManager.KeyguardLock}, for use in tests. */ 228 @Implements(KeyguardManager.KeyguardLock.class) 229 public static class ShadowKeyguardLock { 230 private static boolean keyguardEnabled = true; 231 232 /** 233 * Sets the value to be returned by {@link #isEnabled()} to false. 234 * 235 * @see #isEnabled() 236 */ 237 @Implementation disableKeyguard()238 protected void disableKeyguard() { 239 keyguardEnabled = false; 240 } 241 242 /** 243 * Sets the value to be returned by {@link #isEnabled()} to true. 244 * 245 * @see #isEnabled() 246 */ 247 @Implementation reenableKeyguard()248 protected void reenableKeyguard() { 249 keyguardEnabled = true; 250 } 251 252 /** 253 * For tests, returns the value set via {@link #disableKeyguard()} or {@link 254 * #reenableKeyguard()}, or true by default. 255 * 256 * @see #setKeyguardLocked(boolean) 257 */ isEnabled()258 public boolean isEnabled() { 259 return keyguardEnabled; 260 } 261 262 @Resetter reset()263 public static void reset() { 264 keyguardEnabled = true; 265 } 266 } 267 268 @Resetter reset()269 public static void reset() { 270 deviceLockedForUsers.clear(); 271 deviceSecureForUsers.clear(); 272 inRestrictedInputMode = false; 273 isKeyguardLocked = false; 274 isDeviceLocked = false; 275 isKeyguardSecure = false; 276 isDeviceSecure = false; 277 callback = null; 278 } 279 } 280