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