am 69fd61cb: am a8bbebd4: am b5e47228: Add StrongAuthTracker

* commit '69fd61cb9a487e5993098c93113d86c4fb32c304':
  Add StrongAuthTracker
This commit is contained in:
Adrian Roos
2015-08-22 00:40:47 +00:00
committed by Android Git Automerger
12 changed files with 462 additions and 139 deletions

View File

@@ -90,6 +90,7 @@ LOCAL_SRC_FILES += \
core/java/android/app/IWallpaperManager.aidl \
core/java/android/app/IWallpaperManagerCallback.aidl \
core/java/android/app/admin/IDevicePolicyManager.aidl \
core/java/android/app/trust/IStrongAuthTracker.aidl \
core/java/android/app/trust/ITrustManager.aidl \
core/java/android/app/trust/ITrustListener.aidl \
core/java/android/app/backup/IBackupManager.aidl \

View File

@@ -0,0 +1,26 @@
/*
**
** Copyright 2015, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
package android.app.trust;
/**
* Private API to be notified about strong auth changes
*
* {@hide}
*/
oneway interface IStrongAuthTracker {
void onStrongAuthRequiredChanged(int strongAuthRequired, int userId);
}

View File

@@ -26,11 +26,9 @@ import android.app.trust.ITrustListener;
interface ITrustManager {
void reportUnlockAttempt(boolean successful, int userId);
void reportEnabledTrustAgentsChanged(int userId);
void reportRequireCredentialEntry(int userId);
void registerTrustListener(in ITrustListener trustListener);
void unregisterTrustListener(in ITrustListener trustListener);
void reportKeyguardShowingChanged();
boolean isDeviceLocked(int userId);
boolean isDeviceSecure(int userId);
boolean hasUserAuthenticatedSinceBoot(int userId);
}

View File

@@ -16,13 +16,19 @@
package android.app.trust;
import android.annotation.IntDef;
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}
@@ -72,21 +78,6 @@ public class TrustManager {
}
}
/**
* Reports that trust is disabled until credentials have been entered for user {@param userId}.
*
* Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
*
* @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
*/
public void reportRequireCredentialEntry(int userId) {
try {
mService.reportRequireCredentialEntry(userId);
} catch (RemoteException e) {
onError(e);
}
}
/**
* Reports that the visibility of the keyguard has changed.
*
@@ -147,23 +138,6 @@ public class TrustManager {
}
}
/**
* Checks whether the specified user has been authenticated since the last boot.
*
* @param userId the user id of the user to check for
* @return true if the user has authenticated since boot, false otherwise
*
* Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
*/
public boolean hasUserAuthenticatedSinceBoot(int userId) {
try {
return mService.hasUserAuthenticatedSinceBoot(userId);
} catch (RemoteException e) {
onError(e);
return false;
}
}
private void onError(Exception e) {
Log.e(TAG, "Error while calling TrustManagerService", e);
}

View File

@@ -16,6 +16,7 @@
package com.android.internal.widget;
import android.app.trust.IStrongAuthTracker;
import com.android.internal.widget.VerifyCredentialResponse;
/** {@hide} */
@@ -35,4 +36,7 @@ interface ILockSettings {
boolean checkVoldPassword(int userId);
boolean havePattern(int userId);
boolean havePassword(int userId);
void registerStrongAuthTracker(in IStrongAuthTracker tracker);
void unregisterStrongAuthTracker(in IStrongAuthTracker tracker);
void requireStrongAuth(int strongAuthReason, int userId);
}

View File

@@ -16,18 +16,19 @@
package com.android.internal.widget;
import android.Manifest;
import android.annotation.IntDef;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.admin.DevicePolicyManager;
import android.app.trust.IStrongAuthTracker;
import android.app.trust.TrustManager;
import android.bluetooth.BluetoothClass;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -38,9 +39,12 @@ import android.os.storage.StorageManager;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseIntArray;
import com.google.android.collect.Lists;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -228,7 +232,7 @@ public class LockPatternUtils {
public void reportFailedPasswordAttempt(int userId) {
getDevicePolicyManager().reportFailedPasswordAttempt(userId);
getTrustManager().reportUnlockAttempt(false /* authenticated */, userId);
getTrustManager().reportRequireCredentialEntry(userId);
requireCredentialEntry(userId);
}
public void reportSuccessfulPasswordAttempt(int userId) {
@@ -1163,10 +1167,32 @@ public class LockPatternUtils {
}
/**
* @see android.app.trust.TrustManager#reportRequireCredentialEntry(int)
* Disable trust until credentials have been entered for user {@param userId}.
*
* Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
*
* @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
*/
public void requireCredentialEntry(int userId) {
getTrustManager().reportRequireCredentialEntry(userId);
requireStrongAuth(StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST, userId);
}
/**
* Requests strong authentication for user {@param userId}.
*
* Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
*
* @param strongAuthReason a combination of {@link StrongAuthTracker.StrongAuthFlags} indicating
* the reason for and the strength of the requested authentication.
* @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
*/
public void requireStrongAuth(@StrongAuthTracker.StrongAuthFlags int strongAuthReason,
int userId) {
try {
getLockSettings().requireStrongAuth(strongAuthReason, userId);
} catch (RemoteException e) {
Log.e(TAG, "Error while requesting strong auth: " + e);
}
}
private void onAfterChangingPassword(int userHandle) {
@@ -1198,4 +1224,148 @@ public class LockPatternUtils {
private boolean shouldEncryptWithCredentials(boolean defaultValue) {
return isCredentialRequiredToDecrypt(defaultValue) && !isDoNotAskCredentialsOnBootSet();
}
public void registerStrongAuthTracker(final StrongAuthTracker strongAuthTracker) {
try {
getLockSettings().registerStrongAuthTracker(strongAuthTracker.mStub);
} catch (RemoteException e) {
throw new RuntimeException("Could not register StrongAuthTracker");
}
}
public void unregisterStrongAuthTracker(final StrongAuthTracker strongAuthTracker) {
try {
getLockSettings().unregisterStrongAuthTracker(strongAuthTracker.mStub);
} catch (RemoteException e) {
Log.e(TAG, "Could not unregister StrongAuthTracker", e);
}
}
/**
* Tracks the global strong authentication state.
*/
public static class StrongAuthTracker {
@IntDef(flag = true,
value = { STRONG_AUTH_NOT_REQUIRED,
STRONG_AUTH_REQUIRED_AFTER_BOOT,
STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW,
SOME_AUTH_REQUIRED_AFTER_USER_REQUEST})
@Retention(RetentionPolicy.SOURCE)
public @interface StrongAuthFlags {}
/**
* Strong authentication is not required.
*/
public static final int STRONG_AUTH_NOT_REQUIRED = 0x0;
/**
* Strong authentication is required because the user has not authenticated since boot.
*/
public static final int STRONG_AUTH_REQUIRED_AFTER_BOOT = 0x1;
/**
* Strong authentication is required because a device admin has requested it.
*/
public static final int STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW = 0x2;
/**
* Some authentication is required because the user has temporarily disabled trust.
*/
public static final int SOME_AUTH_REQUIRED_AFTER_USER_REQUEST = 0x4;
public static final int DEFAULT = STRONG_AUTH_REQUIRED_AFTER_BOOT;
private static final int ALLOWING_FINGERPRINT = SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
final SparseIntArray mStrongAuthRequiredForUser = new SparseIntArray();
private final H mHandler;
public StrongAuthTracker() {
this(Looper.myLooper());
}
/**
* @param looper the looper on whose thread calls to {@link #onStrongAuthRequiredChanged}
* will be scheduled.
*/
public StrongAuthTracker(Looper looper) {
mHandler = new H(looper);
}
/**
* Returns {@link #STRONG_AUTH_NOT_REQUIRED} if strong authentication is not required,
* otherwise returns a combination of {@link StrongAuthFlags} indicating why strong
* authentication is required.
*
* @param userId the user for whom the state is queried.
*/
public @StrongAuthFlags int getStrongAuthForUser(int userId) {
return mStrongAuthRequiredForUser.get(userId, DEFAULT);
}
/**
* @return true if unlocking with trust alone is allowed for {@param userId} by the current
* strong authentication requirements.
*/
public boolean isTrustAllowedForUser(int userId) {
return getStrongAuthForUser(userId) == STRONG_AUTH_NOT_REQUIRED;
}
/**
* @return true if unlocking with fingerprint alone is allowed for {@param userId} by the
* current strong authentication requirements.
*/
public boolean isFingerprintAllowedForUser(int userId) {
return (getStrongAuthForUser(userId) & ~ALLOWING_FINGERPRINT) == 0;
}
/**
* Called when the strong authentication requirements for {@param userId} changed.
*/
public void onStrongAuthRequiredChanged(int userId) {
}
void handleStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags,
int userId) {
int oldValue = getStrongAuthForUser(userId);
if (strongAuthFlags != oldValue) {
if (strongAuthFlags == DEFAULT) {
mStrongAuthRequiredForUser.delete(userId);
} else {
mStrongAuthRequiredForUser.put(userId, strongAuthFlags);
}
onStrongAuthRequiredChanged(userId);
}
}
final IStrongAuthTracker.Stub mStub = new IStrongAuthTracker.Stub() {
@Override
public void onStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags,
int userId) {
mHandler.obtainMessage(H.MSG_ON_STRONG_AUTH_REQUIRED_CHANGED,
strongAuthFlags, userId).sendToTarget();
}
};
private class H extends Handler {
static final int MSG_ON_STRONG_AUTH_REQUIRED_CHANGED = 1;
public H(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_ON_STRONG_AUTH_REQUIRED_CHANGED:
handleStrongAuthRequiredChanged(msg.arg1, msg.arg2);
break;
}
}
};
}
}

View File

@@ -58,6 +58,7 @@ import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.widget.LockPatternUtils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -170,7 +171,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private boolean mFingerprintAlreadyAuthenticated;
private boolean mBouncer;
private boolean mBootCompleted;
private boolean mUserHasAuthenticatedSinceBoot;
// Device provisioning state
private boolean mDeviceProvisioned;
@@ -183,6 +183,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
/** Tracks whether strong authentication hasn't been used since quite some time per user. */
private ArraySet<Integer> mStrongAuthTimedOut = new ArraySet<>();
private final StrongAuthTracker mStrongAuthTracker = new StrongAuthTracker();
private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>>
mCallbacks = Lists.newArrayList();
@@ -539,7 +540,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
public boolean isUnlockingWithFingerprintAllowed() {
return mUserHasAuthenticatedSinceBoot && !hasFingerprintUnlockTimedOut(sCurrentUser);
return mStrongAuthTracker.isUnlockingWithFingerprintAllowed()
&& !hasFingerprintUnlockTimedOut(sCurrentUser);
}
public StrongAuthTracker getStrongAuthTracker() {
return mStrongAuthTracker;
}
/**
@@ -827,6 +833,25 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
}
public class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker {
public boolean isUnlockingWithFingerprintAllowed() {
int userId = getCurrentUser();
return isFingerprintAllowedForUser(userId);
}
public boolean hasUserAuthenticatedSinceBoot() {
int userId = getCurrentUser();
return (getStrongAuthForUser(userId)
& STRONG_AUTH_REQUIRED_AFTER_BOOT) == 0;
}
@Override
public void onStrongAuthRequiredChanged(int userId) {
// do something?
}
}
public static KeyguardUpdateMonitor getInstance(Context context) {
if (sInstance == null) {
sInstance = new KeyguardUpdateMonitor(context);
@@ -973,6 +998,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
PERMISSION_SELF, null /* handler */);
mTrustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE);
mTrustManager.registerTrustListener(this);
new LockPatternUtils(context).registerStrongAuthTracker(mStrongAuthTracker);
mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
updateFingerprintListeningState();
@@ -1001,8 +1027,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");
int userId = ActivityManager.getCurrentUser();
if (isUnlockWithFingerprintPossible(userId)) {
mUserHasAuthenticatedSinceBoot = mTrustManager.hasUserAuthenticatedSinceBoot(
ActivityManager.getCurrentUser());
if (mFingerprintCancelSignal != null) {
mFingerprintCancelSignal.cancel();
}

View File

@@ -531,7 +531,7 @@ public class KeyguardViewMediator extends SystemUI {
int currentUser = ActivityManager.getCurrentUser();
if ((mUpdateMonitor.getUserTrustIsManaged(currentUser)
|| mUpdateMonitor.isUnlockWithFingerprintPossible(currentUser))
&& !mTrustManager.hasUserAuthenticatedSinceBoot(currentUser)) {
&& !mUpdateMonitor.getStrongAuthTracker().hasUserAuthenticatedSinceBoot()) {
return KeyguardSecurityView.PROMPT_REASON_RESTART;
} else if (mUpdateMonitor.isUnlockWithFingerprintPossible(currentUser)
&& mUpdateMonitor.hasFingerprintUnlockTimedOut(currentUser)) {

View File

@@ -18,6 +18,7 @@ package com.android.server;
import android.app.admin.DevicePolicyManager;
import android.app.backup.BackupManager;
import android.app.trust.IStrongAuthTracker;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -70,6 +71,7 @@ public class LockSettingsService extends ILockSettings.Stub {
private final Context mContext;
private final LockSettingsStorage mStorage;
private final LockSettingsStrongAuth mStrongAuth = new LockSettingsStrongAuth();
private LockPatternUtils mLockPatternUtils;
private boolean mFirstCallToVold;
@@ -93,6 +95,7 @@ public class LockSettingsService extends ILockSettings.Stub {
filter.addAction(Intent.ACTION_USER_ADDED);
filter.addAction(Intent.ACTION_USER_STARTING);
filter.addAction(Intent.ACTION_USER_REMOVED);
filter.addAction(Intent.ACTION_USER_PRESENT);
mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
mStorage = new LockSettingsStorage(context, new LockSettingsStorage.Callback() {
@@ -122,6 +125,8 @@ public class LockSettingsService extends ILockSettings.Stub {
} else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) {
final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
mStorage.prefetchUser(userHandle);
} else if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
mStrongAuth.reportUnlock(getSendingUserId());
} else if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
if (userHandle > 0) {
@@ -713,6 +718,7 @@ public class LockSettingsService extends ILockSettings.Stub {
private void removeUser(int userId) {
mStorage.removeUser(userId);
mStrongAuth.removeUser(userId);
final KeyStore ks = KeyStore.getInstance();
ks.onUserRemoved(userId);
@@ -727,6 +733,24 @@ public class LockSettingsService extends ILockSettings.Stub {
}
}
@Override
public void registerStrongAuthTracker(IStrongAuthTracker tracker) {
checkPasswordReadPermission(UserHandle.USER_ALL);
mStrongAuth.registerStrongAuthTracker(tracker);
}
@Override
public void unregisterStrongAuthTracker(IStrongAuthTracker tracker) {
checkPasswordReadPermission(UserHandle.USER_ALL);
mStrongAuth.unregisterStrongAuthTracker(tracker);
}
@Override
public void requireStrongAuth(int strongAuthReason, int userId) {
checkWritePermission(userId);
mStrongAuth.requireStrongAuth(strongAuthReason, userId);
}
private static final String[] VALID_SETTINGS = new String[] {
LockPatternUtils.LOCKOUT_PERMANENT_KEY,
LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE,
@@ -797,5 +821,4 @@ public class LockSettingsService extends ILockSettings.Stub {
Slog.e(TAG, "Unable to acquire GateKeeperService");
return null;
}
}

View File

@@ -0,0 +1,167 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.server;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker;
import android.app.trust.IStrongAuthTracker;
import android.os.DeadObjectException;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Slog;
import android.util.SparseIntArray;
import java.util.ArrayList;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
/**
* Keeps track of requests for strong authentication.
*/
public class LockSettingsStrongAuth {
private static final String TAG = "LockSettings";
private static final int MSG_REQUIRE_STRONG_AUTH = 1;
private static final int MSG_REGISTER_TRACKER = 2;
private static final int MSG_UNREGISTER_TRACKER = 3;
private static final int MSG_REMOVE_USER = 4;
private final ArrayList<IStrongAuthTracker> mStrongAuthTrackers = new ArrayList<>();
private final SparseIntArray mStrongAuthForUser = new SparseIntArray();
private void handleAddStrongAuthTracker(IStrongAuthTracker tracker) {
for (int i = 0; i < mStrongAuthTrackers.size(); i++) {
if (mStrongAuthTrackers.get(i).asBinder() == tracker.asBinder()) {
return;
}
}
mStrongAuthTrackers.add(tracker);
for (int i = 0; i < mStrongAuthForUser.size(); i++) {
int key = mStrongAuthForUser.keyAt(i);
int value = mStrongAuthForUser.valueAt(i);
try {
tracker.onStrongAuthRequiredChanged(value, key);
} catch (RemoteException e) {
Slog.e(TAG, "Exception while adding StrongAuthTracker.", e);
}
}
}
private void handleRemoveStrongAuthTracker(IStrongAuthTracker tracker) {
for (int i = 0; i < mStrongAuthTrackers.size(); i++) {
if (mStrongAuthTrackers.get(i).asBinder() == tracker.asBinder()) {
mStrongAuthTrackers.remove(i);
return;
}
}
}
private void handleRequireStrongAuth(int strongAuthReason, int userId) {
if (userId == UserHandle.USER_ALL) {
for (int i = 0; i < mStrongAuthForUser.size(); i++) {
int key = mStrongAuthForUser.keyAt(i);
handleRequireStrongAuthOneUser(strongAuthReason, key);
}
} else {
handleRequireStrongAuthOneUser(strongAuthReason, userId);
}
}
private void handleRequireStrongAuthOneUser(int strongAuthReason, int userId) {
int oldValue = mStrongAuthForUser.get(userId, LockPatternUtils.StrongAuthTracker.DEFAULT);
int newValue = strongAuthReason == STRONG_AUTH_NOT_REQUIRED
? STRONG_AUTH_NOT_REQUIRED
: (oldValue | strongAuthReason);
if (oldValue != newValue) {
mStrongAuthForUser.put(userId, newValue);
notifyStrongAuthTrackers(newValue, userId);
}
}
private void handleRemoveUser(int userId) {
int index = mStrongAuthForUser.indexOfKey(userId);
if (index >= 0) {
mStrongAuthForUser.removeAt(index);
notifyStrongAuthTrackers(StrongAuthTracker.DEFAULT, userId);
}
}
private void notifyStrongAuthTrackers(int strongAuthReason, int userId) {
for (int i = 0; i < mStrongAuthTrackers.size(); i++) {
try {
mStrongAuthTrackers.get(i).onStrongAuthRequiredChanged(strongAuthReason, userId);
} catch (DeadObjectException e) {
Slog.d(TAG, "Removing dead StrongAuthTracker.");
mStrongAuthTrackers.remove(i);
i--;
} catch (RemoteException e) {
Slog.e(TAG, "Exception while notifying StrongAuthTracker.", e);
}
}
}
public void registerStrongAuthTracker(IStrongAuthTracker tracker) {
mHandler.obtainMessage(MSG_REGISTER_TRACKER, tracker).sendToTarget();
}
public void unregisterStrongAuthTracker(IStrongAuthTracker tracker) {
mHandler.obtainMessage(MSG_UNREGISTER_TRACKER, tracker).sendToTarget();
}
public void removeUser(int userId) {
mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget();
}
public void requireStrongAuth(int strongAuthReason, int userId) {
if (userId == UserHandle.USER_ALL || userId >= UserHandle.USER_OWNER) {
mHandler.obtainMessage(MSG_REQUIRE_STRONG_AUTH, strongAuthReason,
userId).sendToTarget();
} else {
throw new IllegalArgumentException(
"userId must be an explicit user id or USER_ALL");
}
}
public void reportUnlock(int userId) {
requireStrongAuth(STRONG_AUTH_NOT_REQUIRED, userId);
}
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_REGISTER_TRACKER:
handleAddStrongAuthTracker((IStrongAuthTracker) msg.obj);
break;
case MSG_UNREGISTER_TRACKER:
handleRemoveStrongAuthTracker((IStrongAuthTracker) msg.obj);
break;
case MSG_REQUIRE_STRONG_AUTH:
handleRequireStrongAuth(msg.arg1, msg.arg2);
break;
case MSG_REMOVE_USER:
handleRemoveUser(msg.arg1);
break;
}
}
};
}

View File

@@ -19,6 +19,7 @@ package com.android.server.trust;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageMonitor;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker;
import com.android.server.SystemService;
import org.xmlpull.v1.XmlPullParser;
@@ -59,6 +60,7 @@ 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;
@@ -96,16 +98,15 @@ public class TrustManagerService extends SystemService {
private static final int MSG_UNREGISTER_LISTENER = 2;
private static final int MSG_DISPATCH_UNLOCK_ATTEMPT = 3;
private static final int MSG_ENABLED_AGENTS_CHANGED = 4;
private static final int MSG_REQUIRE_CREDENTIAL_ENTRY = 5;
private static final int MSG_KEYGUARD_SHOWING_CHANGED = 6;
private static final int MSG_START_USER = 7;
private static final int MSG_CLEANUP_USER = 8;
private static final int MSG_SWITCH_USER = 9;
private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<AgentInfo>();
private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<ITrustListener>();
private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<>();
private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<>();
private final Receiver mReceiver = new Receiver();
private final SparseBooleanArray mUserHasAuthenticated = new SparseBooleanArray();
/* package */ final TrustArchive mArchive = new TrustArchive();
private final Context mContext;
private final LockPatternUtils mLockPatternUtils;
@@ -118,9 +119,6 @@ public class TrustManagerService extends SystemService {
@GuardedBy("mDeviceLockedForUser")
private final SparseBooleanArray mDeviceLockedForUser = new SparseBooleanArray();
@GuardedBy("mUserHasAuthenticatedSinceBoot")
private final SparseBooleanArray mUserHasAuthenticatedSinceBoot = new SparseBooleanArray();
private boolean mTrustAgentsCanRun = false;
private int mCurrentUser = UserHandle.USER_OWNER;
@@ -146,6 +144,7 @@ public class TrustManagerService extends SystemService {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
mReceiver.register(mContext);
mLockPatternUtils.registerStrongAuthTracker(mStrongAuthTracker);
} else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
mTrustAgentsCanRun = true;
refreshAgentList(UserHandle.USER_ALL);
@@ -230,7 +229,7 @@ public class TrustManagerService extends SystemService {
if (!userInfo.supportsSwitchTo()) continue;
if (!mActivityManager.isUserRunning(userInfo.id)) continue;
if (!lockPatternUtils.isSecure(userInfo.id)) continue;
if (!getUserHasAuthenticated(userInfo.id)) continue;
if (!mStrongAuthTracker.isTrustAllowedForUser(userInfo.id)) continue;
DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
final boolean disableTrustAgents =
@@ -509,7 +508,7 @@ public class TrustManagerService extends SystemService {
// Agent dispatch and aggregation
private boolean aggregateIsTrusted(int userId) {
if (!getUserHasAuthenticated(userId)) {
if (!mStrongAuthTracker.isTrustAllowedForUser(userId)) {
return false;
}
for (int i = 0; i < mActiveAgents.size(); i++) {
@@ -524,7 +523,7 @@ public class TrustManagerService extends SystemService {
}
private boolean aggregateIsTrustManaged(int userId) {
if (!getUserHasAuthenticated(userId)) {
if (!mStrongAuthTracker.isTrustAllowedForUser(userId)) {
return false;
}
for (int i = 0; i < mActiveAgents.size(); i++) {
@@ -545,54 +544,6 @@ public class TrustManagerService extends SystemService {
info.agent.onUnlockAttempt(successful);
}
}
if (successful) {
updateUserHasAuthenticated(userId);
}
}
private void updateUserHasAuthenticated(int userId) {
boolean changed = setUserHasAuthenticated(userId);
if (changed) {
refreshAgentList(userId);
}
}
private boolean getUserHasAuthenticated(int userId) {
return mUserHasAuthenticated.get(userId);
}
/**
* @return whether the value has changed
*/
private boolean setUserHasAuthenticated(int userId) {
if (!mUserHasAuthenticated.get(userId)) {
mUserHasAuthenticated.put(userId, true);
synchronized (mUserHasAuthenticatedSinceBoot) {
mUserHasAuthenticatedSinceBoot.put(userId, true);
}
return true;
}
return false;
}
private void clearUserHasAuthenticated(int userId) {
if (userId == UserHandle.USER_ALL) {
mUserHasAuthenticated.clear();
} else {
mUserHasAuthenticated.put(userId, false);
}
}
private boolean getUserHasAuthenticatedSinceBoot(int userId) {
synchronized (mUserHasAuthenticatedSinceBoot) {
return mUserHasAuthenticatedSinceBoot.get(userId);
}
}
private void requireCredentialEntry(int userId) {
clearUserHasAuthenticated(userId);
refreshAgentList(userId);
}
// Listeners
@@ -680,17 +631,6 @@ public class TrustManagerService extends SystemService {
mHandler.sendEmptyMessage(MSG_ENABLED_AGENTS_CHANGED);
}
@Override
public void reportRequireCredentialEntry(int userId) throws RemoteException {
enforceReportPermission();
if (userId == UserHandle.USER_ALL || userId >= UserHandle.USER_OWNER) {
mHandler.obtainMessage(MSG_REQUIRE_CREDENTIAL_ENTRY, userId, 0).sendToTarget();
} else {
throw new IllegalArgumentException(
"userId must be an explicit user id or USER_ALL");
}
}
@Override
public void reportKeyguardShowingChanged() throws RemoteException {
enforceReportPermission();
@@ -734,18 +674,6 @@ public class TrustManagerService extends SystemService {
}
}
@Override
public boolean hasUserAuthenticatedSinceBoot(int userId) throws RemoteException {
mContext.enforceCallingOrSelfPermission(
Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, null);
long token = Binder.clearCallingIdentity();
try {
return getUserHasAuthenticatedSinceBoot(userId);
} finally {
Binder.restoreCallingIdentity(token);
}
}
private void enforceReportPermission() {
mContext.enforceCallingOrSelfPermission(
Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, "reporting trust events");
@@ -794,9 +722,8 @@ public class TrustManagerService extends SystemService {
fout.print(": trusted=" + dumpBool(aggregateIsTrusted(user.id)));
fout.print(", trustManaged=" + dumpBool(aggregateIsTrustManaged(user.id)));
fout.print(", deviceLocked=" + dumpBool(isDeviceLockedInner(user.id)));
fout.print(", hasAuthenticated=" + dumpBool(getUserHasAuthenticated(user.id)));
fout.print(", hasAuthenticatedSinceBoot="
+ dumpBool(getUserHasAuthenticatedSinceBoot(user.id)));
fout.print(", strongAuthRequired=" + dumpHex(
mStrongAuthTracker.getStrongAuthForUser(user.id)));
fout.println();
fout.println(" Enabled agents:");
boolean duplicateSimpleNames = false;
@@ -831,6 +758,10 @@ public class TrustManagerService extends SystemService {
private String dumpBool(boolean b) {
return b ? "1" : "0";
}
private String dumpHex(int i) {
return "0x" + Integer.toHexString(i);
}
};
private int resolveProfileParent(int userId) {
@@ -864,9 +795,6 @@ public class TrustManagerService extends SystemService {
// This is also called when the security mode of a user changes.
refreshDeviceLockedForUser(UserHandle.USER_ALL);
break;
case MSG_REQUIRE_CREDENTIAL_ENTRY:
requireCredentialEntry(msg.arg1);
break;
case MSG_KEYGUARD_SHOWING_CHANGED:
refreshDeviceLockedForUser(mCurrentUser);
break;
@@ -900,6 +828,13 @@ public class TrustManagerService extends SystemService {
}
};
private final StrongAuthTracker mStrongAuthTracker = new StrongAuthTracker() {
@Override
public void onStrongAuthRequiredChanged(int userId) {
refreshAgentList(userId);
}
};
private class Receiver extends BroadcastReceiver {
@Override
@@ -908,8 +843,6 @@ public class TrustManagerService extends SystemService {
if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
refreshAgentList(getSendingUserId());
updateDevicePolicyFeatures();
} else if (Intent.ACTION_USER_PRESENT.equals(action)) {
updateUserHasAuthenticated(getSendingUserId());
} else if (Intent.ACTION_USER_ADDED.equals(action)) {
int userId = getUserId(intent);
if (userId > 0) {
@@ -918,7 +851,6 @@ public class TrustManagerService extends SystemService {
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
int userId = getUserId(intent);
if (userId > 0) {
mUserHasAuthenticated.delete(userId);
synchronized (mUserIsTrusted) {
mUserIsTrusted.delete(userId);
}

View File

@@ -21,6 +21,7 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA;
import static android.content.pm.PackageManager.GET_UNINSTALLED_PACKAGES;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.END_TAG;
import static org.xmlpull.v1.XmlPullParser.TEXT;
@@ -44,6 +45,7 @@ import android.app.admin.DevicePolicyManagerInternal;
import android.app.admin.IDevicePolicyManager;
import android.app.admin.SystemUpdatePolicy;
import android.app.backup.IBackupManager;
import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -2957,7 +2959,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
boolean requireEntry = (flags & DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY) != 0;
if (requireEntry) {
utils.requireCredentialEntry(UserHandle.USER_ALL);
utils.requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW,
UserHandle.USER_ALL);
}
synchronized (this) {
int newOwner = requireEntry ? callingUid : -1;
@@ -3089,7 +3092,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
mPowerManager.goToSleep(SystemClock.uptimeMillis(),
PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN, 0);
// Ensure the device is locked
new LockPatternUtils(mContext).requireCredentialEntry(UserHandle.USER_ALL);
new LockPatternUtils(mContext).requireStrongAuth(
STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW, UserHandle.USER_ALL);
getWindowManager().lockNow(null);
} catch (RemoteException e) {
} finally {