diff options
9 files changed, 95 insertions, 7 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index c39c70a46bfd..ed0f26e93615 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -38772,6 +38772,7 @@ package android.service.trust { method public final android.os.IBinder onBind(android.content.Intent); method public boolean onConfigure(java.util.List<android.os.PersistableBundle>); method public void onDeviceLocked(); + method public void onDeviceUnlockLockout(long); method public void onDeviceUnlocked(); method public void onTrustTimeout(); method public void onUnlockAttempt(boolean); diff --git a/core/java/android/app/trust/ITrustManager.aidl b/core/java/android/app/trust/ITrustManager.aidl index d3d02e59c228..a10de45d115b 100644 --- a/core/java/android/app/trust/ITrustManager.aidl +++ b/core/java/android/app/trust/ITrustManager.aidl @@ -25,6 +25,7 @@ import android.app.trust.ITrustListener; */ interface ITrustManager { void reportUnlockAttempt(boolean successful, int userId); + void reportUnlockLockout(int timeoutMs, int userId); void reportEnabledTrustAgentsChanged(int userId); void registerTrustListener(in ITrustListener trustListener); void unregisterTrustListener(in ITrustListener trustListener); diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java index 0f5cb6f4b8e1..a64a023fec6b 100644 --- a/core/java/android/app/trust/TrustManager.java +++ b/core/java/android/app/trust/TrustManager.java @@ -81,6 +81,26 @@ public class TrustManager { } /** + * Reports that user {@param userId} has entered a temporary device lockout. + * + * This generally occurs when the user has unsuccessfully tried to unlock the device too many + * times. The user will then be unable to unlock the device until a set amount of time has + * elapsed. + * + * @param timeout The amount of time that needs to elapse, in milliseconds, until the user may + * attempt to unlock the device again. + * + * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission. + */ + public void reportUnlockLockout(int timeoutMs, int userId) { + try { + mService.reportUnlockLockout(timeoutMs, userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Reports that the list of enabled trust agents changed for user {@param userId}. * * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission. diff --git a/core/java/android/service/trust/ITrustAgentService.aidl b/core/java/android/service/trust/ITrustAgentService.aidl index f07d0d032ed1..22b4d09e5f70 100644 --- a/core/java/android/service/trust/ITrustAgentService.aidl +++ b/core/java/android/service/trust/ITrustAgentService.aidl @@ -24,6 +24,7 @@ import android.service.trust.ITrustAgentServiceCallback; */ interface ITrustAgentService { oneway void onUnlockAttempt(boolean successful); + oneway void onUnlockLockout(int timeoutMs); oneway void onTrustTimeout(); oneway void onDeviceLocked(); oneway void onDeviceUnlocked(); diff --git a/core/java/android/service/trust/TrustAgentService.java b/core/java/android/service/trust/TrustAgentService.java index 9d7ffad5052e..0d5177d23413 100644 --- a/core/java/android/service/trust/TrustAgentService.java +++ b/core/java/android/service/trust/TrustAgentService.java @@ -123,6 +123,7 @@ public class TrustAgentService extends Service { private static final int MSG_TRUST_TIMEOUT = 3; private static final int MSG_DEVICE_LOCKED = 4; private static final int MSG_DEVICE_UNLOCKED = 5; + private static final int MSG_UNLOCK_LOCKOUT = 6; /** * Class containing raw data for a given configuration request. @@ -151,6 +152,9 @@ public class TrustAgentService extends Service { case MSG_UNLOCK_ATTEMPT: onUnlockAttempt(msg.arg1 != 0); break; + case MSG_UNLOCK_LOCKOUT: + onDeviceUnlockLockout(msg.arg1); + break; case MSG_CONFIGURE: ConfigurationData data = (ConfigurationData) msg.obj; boolean result = onConfigure(data.options); @@ -226,6 +230,21 @@ public class TrustAgentService extends Service { public void onDeviceUnlocked() { } + /** + * Called when the device enters a temporary unlock lockout. + * + * <p>This occurs when the user has consecutively failed to unlock the device too many times, + * and must wait until a timeout has passed to perform another attempt. The user may then only + * use strong authentication mechanisms (PIN, pattern or password) to unlock the device. + * Calls to {@link #grantTrust(CharSequence, long, int)} will be ignored until the user has + * unlocked the device and {@link #onDeviceUnlocked()} is called. + * + * @param timeoutMs The amount of time, in milliseconds, that needs to elapse before the user + * can attempt to unlock the device again. + */ + public void onDeviceUnlockLockout(long timeoutMs) { + } + private void onError(String msg) { Slog.v(TAG, "Remote exception while " + msg); } @@ -366,6 +385,11 @@ public class TrustAgentService extends Service { mHandler.obtainMessage(MSG_UNLOCK_ATTEMPT, successful ? 1 : 0, 0).sendToTarget(); } + @Override + public void onUnlockLockout(int timeoutMs) { + mHandler.obtainMessage(MSG_UNLOCK_LOCKOUT, timeoutMs, 0).sendToTarget(); + } + @Override /* Binder API */ public void onTrustTimeout() { mHandler.sendEmptyMessage(MSG_TRUST_TIMEOUT); diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index a43f3a72782c..a29882b497b4 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -298,6 +298,10 @@ public class LockPatternUtils { getTrustManager().reportUnlockAttempt(true /* authenticated */, userId); } + public void reportPasswordLockout(int timeoutMs, int userId) { + getTrustManager().reportUnlockLockout(timeoutMs, userId); + } + public int getCurrentFailedPasswordAttempts(int userId) { return getDevicePolicyManager().getCurrentFailedPasswordAttempts(userId); } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java index 91c943de756c..8cdb906a0e56 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -290,6 +290,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe monitor.reportFailedStrongAuthUnlockAttempt(userId); mLockPatternUtils.reportFailedPasswordAttempt(userId); if (timeoutMs > 0) { + mLockPatternUtils.reportPasswordLockout(timeoutMs, userId); showTimeoutDialog(userId, timeoutMs); } } diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java index e7c5384b9932..6c1648cb0d16 100644 --- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java +++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java @@ -321,6 +321,19 @@ public class TrustAgentWrapper { } /** + * @see android.service.trust.TrustAgentService#onUnlockLockout(int) + */ + public void onUnlockLockout(int timeoutMs) { + try { + if (mTrustAgentService != null) { + mTrustAgentService.onUnlockLockout(timeoutMs); + } + } catch (RemoteException e) { + onError(e); + } + } + + /** * @see android.service.trust.TrustAgentService#onDeviceLocked() */ public void onDeviceLocked() { diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index c69b87c53763..71b725e10769 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -105,6 +105,7 @@ public class TrustManagerService extends SystemService { private static final int MSG_FLUSH_TRUST_USUALLY_MANAGED = 10; private static final int MSG_UNLOCK_USER = 11; private static final int MSG_STOP_USER = 12; + private static final int MSG_DISPATCH_UNLOCK_LOCKOUT = 13; private static final int TRUST_USUALLY_MANAGED_FLUSH_DELAY = 2 * 60 * 1000; @@ -335,13 +336,16 @@ public class TrustManagerService extends SystemService { if (!mStrongAuthTracker.canAgentsRunForUser(userInfo.id)) { int flag = mStrongAuthTracker.getStrongAuthForUser(userInfo.id); - if (flag != StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT - || !directUnlock) { - if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id - + ": prevented by StrongAuthTracker = 0x" - + Integer.toHexString(mStrongAuthTracker.getStrongAuthForUser( - userInfo.id))); - continue; + if (flag != StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) { + if (flag != StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT + || !directUnlock) { + if (DEBUG) + Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id + + ": prevented by StrongAuthTracker = 0x" + + Integer.toHexString(mStrongAuthTracker.getStrongAuthForUser( + userInfo.id))); + continue; + } } } @@ -650,6 +654,15 @@ public class TrustManagerService extends SystemService { } } + private void dispatchUnlockLockout(int timeoutMs, int userId) { + for (int i = 0; i < mActiveAgents.size(); i++) { + AgentInfo info = mActiveAgents.valueAt(i); + if (info.userId == userId) { + info.agent.onUnlockLockout(timeoutMs); + } + } + } + // Listeners private void addListener(ITrustListener listener) { @@ -745,6 +758,13 @@ public class TrustManagerService extends SystemService { } @Override + public void reportUnlockLockout(int timeoutMs, int userId) throws RemoteException { + enforceReportPermission(); + mHandler.obtainMessage(MSG_DISPATCH_UNLOCK_LOCKOUT, timeoutMs, userId) + .sendToTarget(); + } + + @Override public void reportEnabledTrustAgentsChanged(int userId) throws RemoteException { enforceReportPermission(); // coalesce refresh messages. @@ -975,6 +995,9 @@ public class TrustManagerService extends SystemService { case MSG_DISPATCH_UNLOCK_ATTEMPT: dispatchUnlockAttempt(msg.arg1 != 0, msg.arg2); break; + case MSG_DISPATCH_UNLOCK_LOCKOUT: + dispatchUnlockLockout(msg.arg1, msg.arg2); + break; case MSG_ENABLED_AGENTS_CHANGED: refreshAgentList(UserHandle.USER_ALL); // This is also called when the security mode of a user changes. |