diff options
author | 2016-01-25 17:20:11 +0000 | |
---|---|---|
committer | 2016-01-25 17:20:11 +0000 | |
commit | 4afbe99127773f71fb35b31cc1becd828867ccb5 (patch) | |
tree | 211c2b4ac993254b4209025e8b41d0cbbc29c604 | |
parent | 0f9f67132c104d15a33466583a8f4ebb529d213b (diff) | |
parent | c13723f22e476b4558061942c001ee62eaca79e4 (diff) |
Merge "Improved trust error messaging (1/2)"
9 files changed, 162 insertions, 15 deletions
diff --git a/core/java/android/app/trust/ITrustManager.aidl b/core/java/android/app/trust/ITrustManager.aidl index a3fe6abab219..d3d02e59c228 100644 --- a/core/java/android/app/trust/ITrustManager.aidl +++ b/core/java/android/app/trust/ITrustManager.aidl @@ -32,4 +32,5 @@ interface ITrustManager { void setDeviceLockedForUser(int userId, boolean locked); boolean isDeviceLocked(int userId); boolean isDeviceSecure(int userId); + boolean isTrustUsuallyManaged(int userId); } diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java index 88ba874083b5..2bbc54f7e4e6 100644 --- a/core/java/android/app/trust/TrustManager.java +++ b/core/java/android/app/trust/TrustManager.java @@ -16,21 +16,17 @@ package android.app.trust; +import com.android.internal.widget.LockPatternUtils; + import android.Manifest; -import android.annotation.IntDef; import android.annotation.RequiresPermission; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.RemoteException; -import android.os.UserHandle; import android.util.ArrayMap; import android.util.Log; -import android.util.SparseIntArray; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; /** * See {@link com.android.server.trust.TrustManagerService} @@ -158,6 +154,21 @@ public class TrustManager { } } + /** + * @return whether {@userId} has enabled and configured trust agents. Ignores short-term + * unavailability of trust due to {@link LockPatternUtils.StrongAuthTracker}. + */ + @RequiresPermission(android.Manifest.permission.TRUST_LISTENER) + public boolean isTrustUsuallyManaged(int userId) { + try { + return mService.isTrustUsuallyManaged(userId); + } catch (RemoteException e) { + return false; + } + } + + + private void onError(Exception e) { Log.e(TAG, "Error while calling TrustManagerService", e); } diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 4e8f19cd0f95..a1b18fee1032 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -136,6 +136,7 @@ public class LockPatternUtils { private static final String LOCK_SCREEN_DEVICE_OWNER_INFO = "lockscreen.device_owner_info"; private static final String ENABLED_TRUST_AGENTS = "lockscreen.enabledtrustagents"; + private static final String IS_TRUST_USUALLY_MANAGED = "lockscreen.istrustusuallymanaged"; private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge"; @@ -149,6 +150,30 @@ public class LockPatternUtils { private ILockSettings mLockSettingsService; private UserManager mUserManager; + /** + * Use {@link TrustManager#isTrustUsuallyManaged(int)}. + * + * This returns the lazily-peristed value and should only be used by TrustManagerService. + */ + public boolean isTrustUsuallyManaged(int userId) { + if (!(mLockSettingsService instanceof ILockSettings.Stub)) { + throw new IllegalStateException("May only be called by TrustManagerService. " + + "Use TrustManager.isTrustUsuallyManaged()"); + } + try { + return getLockSettings().getBoolean(IS_TRUST_USUALLY_MANAGED, false, userId); + } catch (RemoteException e) { + return false; + } + } + + public void setTrustUsuallyManaged(boolean managed, int userId) { + try { + getLockSettings().setBoolean(IS_TRUST_USUALLY_MANAGED, managed, userId); + } catch (RemoteException e) { + // System dead. + } + } public static final class RequestThrottledException extends Exception { private int mTimeoutMs; diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java index 3a7e6d0a9b54..63dec8b70427 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java @@ -117,8 +117,10 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView return R.string.kg_prompt_reason_restart_password; case PROMPT_REASON_TIMEOUT: return R.string.kg_prompt_reason_timeout_password; - default: + case PROMPT_REASON_NONE: return 0; + default: + return R.string.kg_prompt_reason_timeout_password; } } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java index 2a2f5a0c9730..be2701d0e16d 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java @@ -339,7 +339,11 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_timeout_pattern, true /* important */); break; + case PROMPT_REASON_NONE: + break; default: + mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_timeout_pattern, + true /* important */); break; } } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java index f51e10fd0191..cedd88d44807 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java @@ -103,8 +103,10 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView return R.string.kg_prompt_reason_restart_pin; case PROMPT_REASON_TIMEOUT: return R.string.kg_prompt_reason_timeout_pin; - default: + case PROMPT_REASON_NONE: return 0; + default: + return R.string.kg_prompt_reason_timeout_pin; } } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java index 38302fb7ad71..aa74940492f2 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java @@ -34,6 +34,26 @@ public interface KeyguardSecurityView { int PROMPT_REASON_TIMEOUT = 2; /** + * Strong auth is required because a device admin requested it. + */ + int PROMPT_REASON_DEVICE_ADMIN = 3; + + /** + * Some auth is required because the user force locked. + */ + int PROMPT_REASON_USER_REQUEST = 4; + + /** + * Some auth is required because too many wrong credentials led to a lockout. + */ + int PROMPT_REASON_AFTER_LOCKOUT = 5; + + /** + * Some auth is required because a single wrong credential has been tried. + */ + int PROMPT_REASON_WRONG_CREDENTIAL = 6; + + /** * Interface back to keyguard to tell it when security * @param callback */ diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 704de97a2fa8..0475c72cabe2 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -84,6 +84,10 @@ import java.util.ArrayList; import java.util.List; import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT; +import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST; +import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL; +import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW; +import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT; /** * Mediates requests related to the keyguard. This includes queries about the @@ -550,14 +554,28 @@ public class KeyguardViewMediator extends SystemUI { @Override public int getBouncerPromptReason() { int currentUser = ActivityManager.getCurrentUser(); - if ((mUpdateMonitor.getUserTrustIsManaged(currentUser) - || mUpdateMonitor.isUnlockWithFingerprintPossible(currentUser)) - && !mUpdateMonitor.getStrongAuthTracker().hasUserAuthenticatedSinceBoot()) { + boolean trust = mTrustManager.isTrustUsuallyManaged(currentUser); + boolean fingerprint = mUpdateMonitor.isUnlockWithFingerprintPossible(currentUser); + boolean any = trust || fingerprint; + KeyguardUpdateMonitor.StrongAuthTracker strongAuthTracker = + mUpdateMonitor.getStrongAuthTracker(); + int strongAuth = strongAuthTracker.getStrongAuthForUser(currentUser); + + if (any && !strongAuthTracker.hasUserAuthenticatedSinceBoot()) { return KeyguardSecurityView.PROMPT_REASON_RESTART; - } else if (mUpdateMonitor.isUnlockWithFingerprintPossible(currentUser) - && mUpdateMonitor.hasFingerprintUnlockTimedOut(currentUser)) { + } else if (fingerprint && mUpdateMonitor.hasFingerprintUnlockTimedOut(currentUser)) { return KeyguardSecurityView.PROMPT_REASON_TIMEOUT; + } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW) != 0) { + return KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN; + } else if (trust && (strongAuth & SOME_AUTH_REQUIRED_AFTER_USER_REQUEST) != 0) { + return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST; + } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0) { + return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT; + } else if (trust && (strongAuth & SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL) != 0) { + return KeyguardSecurityView.PROMPT_REASON_WRONG_CREDENTIAL; } + + return KeyguardSecurityView.PROMPT_REASON_NONE; } }; diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 1d498e1894eb..3452f41eb587 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -60,7 +60,6 @@ import android.util.AttributeSet; import android.util.Log; import android.util.Slog; import android.util.SparseBooleanArray; -import android.util.SparseIntArray; import android.util.Xml; import android.view.IWindowManager; import android.view.WindowManagerGlobal; @@ -103,6 +102,9 @@ public class TrustManagerService extends SystemService { private static final int MSG_CLEANUP_USER = 8; private static final int MSG_SWITCH_USER = 9; private static final int MSG_SET_DEVICE_LOCKED = 10; + private static final int MSG_FLUSH_TRUST_USUALLY_MANAGED = 11; + + public static final int TRUST_USUALLY_MANAGED_FLUSH_DELAY = 2 * 60 * 1000; private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<>(); private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<>(); @@ -120,6 +122,9 @@ public class TrustManagerService extends SystemService { @GuardedBy("mDeviceLockedForUser") private final SparseBooleanArray mDeviceLockedForUser = new SparseBooleanArray(); + @GuardedBy("mDeviceLockedForUser") + private final SparseBooleanArray mTrustUsuallyManagedForUser = new SparseBooleanArray(); + private boolean mTrustAgentsCanRun = false; private int mCurrentUser = UserHandle.USER_SYSTEM; @@ -187,7 +192,12 @@ public class TrustManagerService extends SystemService { } public void updateTrust(int userId, int flags) { - dispatchOnTrustManagedChanged(aggregateIsTrustManaged(userId), userId); + boolean managed = aggregateIsTrustManaged(userId); + dispatchOnTrustManagedChanged(managed, userId); + if (mStrongAuthTracker.isTrustAllowedForUser(userId) + && isTrustUsuallyManagedInternal(userId) != managed) { + updateTrustUsuallyManaged(userId, managed); + } boolean trusted = aggregateIsTrusted(userId); boolean changed; synchronized (mUserIsTrusted) { @@ -200,6 +210,18 @@ public class TrustManagerService extends SystemService { } } + private void updateTrustUsuallyManaged(int userId, boolean managed) { + synchronized (mTrustUsuallyManagedForUser) { + mTrustUsuallyManagedForUser.put(userId, managed); + } + // Wait a few minutes before committing to flash, in case the trust agent is transiently not + // managing trust (crashed, needs to acknowledge DPM restrictions, etc). + mHandler.removeMessages(MSG_FLUSH_TRUST_USUALLY_MANAGED); + mHandler.sendMessageDelayed( + mHandler.obtainMessage(MSG_FLUSH_TRUST_USUALLY_MANAGED), + TRUST_USUALLY_MANAGED_FLUSH_DELAY); + } + void refreshAgentList(int userId) { if (DEBUG) Slog.d(TAG, "refreshAgentList()"); if (!mTrustAgentsCanRun) { @@ -787,8 +809,37 @@ public class TrustManagerService extends SystemService { mHandler.obtainMessage(MSG_SET_DEVICE_LOCKED, value ? 1 : 0, userId) .sendToTarget(); } + + @Override + public boolean isTrustUsuallyManaged(int userId) { + mContext.enforceCallingPermission(Manifest.permission.TRUST_LISTENER, + "query trust state"); + return isTrustUsuallyManagedInternal(userId); + } }; + private boolean isTrustUsuallyManagedInternal(int userId) { + synchronized (mTrustUsuallyManagedForUser) { + int i = mTrustUsuallyManagedForUser.indexOfKey(userId); + if (i >= 0) { + return mTrustUsuallyManagedForUser.valueAt(i); + } + } + // It's not in memory yet, get the value from persisted storage instead + boolean persistedValue = mLockPatternUtils.isTrustUsuallyManaged(userId); + synchronized (mTrustUsuallyManagedForUser) { + int i = mTrustUsuallyManagedForUser.indexOfKey(userId); + if (i >= 0) { + // Someone set the trust usually managed in the mean time. Better use that. + return mTrustUsuallyManagedForUser.valueAt(i); + } else { + // .. otherwise it's safe to cache the fetched value now. + mTrustUsuallyManagedForUser.put(userId, persistedValue); + return persistedValue; + } + } + } + private int resolveProfileParent(int userId) { long identity = Binder.clearCallingIdentity(); try { @@ -834,6 +885,19 @@ public class TrustManagerService extends SystemService { case MSG_SET_DEVICE_LOCKED: setDeviceLockedForUser(msg.arg2, msg.arg1 != 0); break; + case MSG_FLUSH_TRUST_USUALLY_MANAGED: + SparseBooleanArray usuallyManaged; + synchronized (mTrustUsuallyManagedForUser) { + usuallyManaged = mTrustUsuallyManagedForUser.clone(); + } + + for (int i = 0; i < usuallyManaged.size(); i++) { + int userId = usuallyManaged.keyAt(i); + boolean value = usuallyManaged.valueAt(i); + if (value != mLockPatternUtils.isTrustUsuallyManaged(userId)) { + mLockPatternUtils.setTrustUsuallyManaged(value, userId); + } + } } } }; |