am 4e312d81: Merge "Add device locked API for TrustAgentService" into lmp-mr1-dev

automerge: 62a7d53

* commit '62a7d5334315b4153f1da1112f945d13f72e0381':
  Add device locked API for TrustAgentService
This commit is contained in:
Adrian Roos
2014-11-21 02:47:16 +00:00
committed by android-build-merger
10 changed files with 270 additions and 41 deletions

View File

@@ -29,5 +29,6 @@ interface ITrustManager {
void reportRequireCredentialEntry(int userId);
void registerTrustListener(in ITrustListener trustListener);
void unregisterTrustListener(in ITrustListener trustListener);
void reportKeyguardShowingChanged();
boolean isDeviceLocked(int userId);
}

View File

@@ -87,6 +87,19 @@ public class TrustManager {
}
}
/**
* Reports that the visibility of the keyguard has changed.
*
* Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
*/
public void reportKeyguardShowingChanged() {
try {
mService.reportKeyguardShowingChanged();
} catch (RemoteException e) {
onError(e);
}
}
/**
* Registers a listener for trust events.
*

View File

@@ -25,6 +25,8 @@ import android.service.trust.ITrustAgentServiceCallback;
interface ITrustAgentService {
oneway void onUnlockAttempt(boolean successful);
oneway void onTrustTimeout();
oneway void onDeviceLocked();
oneway void onDeviceUnlocked();
oneway void onConfigure(in List<PersistableBundle> options, IBinder token);
oneway void setCallback(ITrustAgentServiceCallback callback);
}

View File

@@ -92,6 +92,8 @@ public class TrustAgentService extends Service {
private static final int MSG_UNLOCK_ATTEMPT = 1;
private static final int MSG_CONFIGURE = 2;
private static final int MSG_TRUST_TIMEOUT = 3;
private static final int MSG_DEVICE_LOCKED = 4;
private static final int MSG_DEVICE_UNLOCKED = 5;
/**
* Class containing raw data for a given configuration request.
@@ -134,6 +136,12 @@ public class TrustAgentService extends Service {
case MSG_TRUST_TIMEOUT:
onTrustTimeout();
break;
case MSG_DEVICE_LOCKED:
onDeviceLocked();
break;
case MSG_DEVICE_UNLOCKED:
onDeviceUnlocked();
break;
}
}
};
@@ -173,6 +181,20 @@ public class TrustAgentService extends Service {
public void onTrustTimeout() {
}
/**
* Called when the device enters a state where a PIN, pattern or
* password must be entered to unlock it.
*/
public void onDeviceLocked() {
}
/**
* Called when the device leaves a state where a PIN, pattern or
* password must be entered to unlock it.
*/
public void onDeviceUnlocked() {
}
private void onError(String msg) {
Slog.v(TAG, "Remote exception while " + msg);
}
@@ -300,6 +322,16 @@ public class TrustAgentService extends Service {
.sendToTarget();
}
@Override
public void onDeviceLocked() throws RemoteException {
mHandler.obtainMessage(MSG_DEVICE_LOCKED).sendToTarget();
}
@Override
public void onDeviceUnlocked() throws RemoteException {
mHandler.obtainMessage(MSG_DEVICE_UNLOCKED).sendToTarget();
}
@Override /* Binder API */
public void setCallback(ITrustAgentServiceCallback callback) {
synchronized (mLock) {

View File

@@ -44,6 +44,12 @@
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:text="Report unlock attempts" />
<CheckBox android:id="@+id/report_device_locked"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:text="Report device locked or unlocked" />
<LinearLayout
android:layout_width="match_parent"

View File

@@ -56,6 +56,7 @@ public class SampleTrustAgent extends TrustAgentService
= "preference.report_unlock_attempts";
private static final String PREFERENCE_MANAGING_TRUST
= "preference.managing_trust";
private static final String PREFERENCE_REPORT_DEVICE_LOCKED = "preference.report_device_locked";
private static final String TAG = "SampleTrustAgent";
@@ -80,17 +81,37 @@ public class SampleTrustAgent extends TrustAgentService
@Override
public void onTrustTimeout() {
super.onTrustTimeout();
Toast.makeText(this, "onTrustTimeout(): timeout expired", Toast.LENGTH_SHORT).show();
logAndShowToast("onTrustTimeout(): timeout expired");
}
@Override
public void onDeviceLocked() {
super.onDeviceLocked();
if (getReportDeviceLocked(this)) {
logAndShowToast("onDeviceLocked(): device is now locked");
}
}
@Override
public void onDeviceUnlocked() {
super.onDeviceUnlocked();
if (getReportDeviceLocked(this)) {
logAndShowToast("onDeviceUnlocked(): device is now unlocked");
}
}
@Override
public void onUnlockAttempt(boolean successful) {
if (getReportUnlockAttempts(this)) {
Toast.makeText(this, "onUnlockAttempt(successful=" + successful + ")",
Toast.LENGTH_SHORT).show();
logAndShowToast("onUnlockAttempt(successful=" + successful + ")");
}
}
private void logAndShowToast(String text) {
Log.i(TAG, text);
Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
}
@Override
public boolean onConfigure(List<PersistableBundle> options) {
if (options != null) {
@@ -125,8 +146,7 @@ public class SampleTrustAgent extends TrustAgentService
intent.getLongExtra(EXTRA_DURATION, 0),
intent.getBooleanExtra(EXTRA_INITIATED_BY_USER, false));
} catch (IllegalStateException e) {
Toast.makeText(context,
"IllegalStateException: " + e.getMessage(), Toast.LENGTH_SHORT).show();
logAndShowToast("IllegalStateException: " + e.getMessage());
}
} else if (ACTION_REVOKE_TRUST.equals(action)) {
revokeTrust();
@@ -160,6 +180,18 @@ public class SampleTrustAgent extends TrustAgentService
return sharedPreferences.getBoolean(PREFERENCE_REPORT_UNLOCK_ATTEMPTS, false);
}
public static void setReportDeviceLocked(Context context, boolean enabled) {
SharedPreferences sharedPreferences = PreferenceManager
.getDefaultSharedPreferences(context);
sharedPreferences.edit().putBoolean(PREFERENCE_REPORT_DEVICE_LOCKED, enabled).apply();
}
public static boolean getReportDeviceLocked(Context context) {
SharedPreferences sharedPreferences = PreferenceManager
.getDefaultSharedPreferences(context);
return sharedPreferences.getBoolean(PREFERENCE_REPORT_DEVICE_LOCKED, false);
}
public static void setIsManagingTrust(Context context, boolean enabled) {
SharedPreferences sharedPreferences = PreferenceManager
.getDefaultSharedPreferences(context);

View File

@@ -31,6 +31,7 @@ public class SampleTrustAgentSettings extends Activity implements View.OnClickLi
private static final int TRUST_DURATION_MS = 30 * 1000;
private CheckBox mReportUnlockAttempts;
private CheckBox mReportDeviceLocked;
private CheckBox mManagingTrust;
private TextView mCheckDeviceLockedResult;
@@ -53,6 +54,9 @@ public class SampleTrustAgentSettings extends Activity implements View.OnClickLi
mReportUnlockAttempts = (CheckBox) findViewById(R.id.report_unlock_attempts);
mReportUnlockAttempts.setOnCheckedChangeListener(this);
mReportDeviceLocked = (CheckBox) findViewById(R.id.report_device_locked);
mReportDeviceLocked.setOnCheckedChangeListener(this);
mManagingTrust = (CheckBox) findViewById(R.id.managing_trust);
mManagingTrust.setOnCheckedChangeListener(this);
@@ -88,6 +92,8 @@ public class SampleTrustAgentSettings extends Activity implements View.OnClickLi
SampleTrustAgent.setReportUnlockAttempts(this, isChecked);
} else if (buttonView == mManagingTrust) {
SampleTrustAgent.setIsManagingTrust(this, isChecked);
} else if (buttonView == mReportDeviceLocked) {
SampleTrustAgent.setReportDeviceLocked(this, isChecked);
}
}

View File

@@ -23,6 +23,7 @@ import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.SearchManager;
import android.app.StatusBarManager;
import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -187,8 +188,9 @@ public class KeyguardViewMediator extends SystemUI {
/** High level access to the window manager for dismissing keyguard animation */
private IWindowManager mWM;
/** UserManager for querying number of users */
private UserManager mUserManager;
/** TrustManager for letting it know when we change visibility */
private TrustManager mTrustManager;
/** SearchManager for determining whether or not search assistant is available */
private SearchManager mSearchManager;
@@ -484,7 +486,8 @@ public class KeyguardViewMediator extends SystemUI {
private void setup() {
mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mWM = WindowManagerGlobal.getWindowManagerService();
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mTrustManager = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
mShowKeyguardWakeLock.setReferenceCounted(false);
@@ -501,6 +504,7 @@ public class KeyguardViewMediator extends SystemUI {
// Assume keyguard is showing (unless it's disabled) until we know for sure...
mShowing = !shouldWaitForProvisioning() && !mLockPatternUtils.isLockScreenDisabled();
mTrustManager.reportKeyguardShowingChanged();
mStatusBarKeyguardViewManager = new StatusBarKeyguardViewManager(mContext,
mViewMediatorCallback, mLockPatternUtils);
@@ -931,7 +935,7 @@ public class KeyguardViewMediator extends SystemUI {
if (mLockPatternUtils.checkVoldPassword()) {
if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted");
// Without this, settings is not enabled until the lock screen first appears
mShowing = false;
setShowing(false);
hideLocked();
return;
}
@@ -1249,7 +1253,7 @@ public class KeyguardViewMediator extends SystemUI {
mStatusBarKeyguardViewManager.show(options);
mHiding = false;
mShowing = true;
setShowing(true);
resetKeyguardDonePendingLocked();
mHideAnimationRun = false;
updateActivityLockScreenState();
@@ -1328,7 +1332,7 @@ public class KeyguardViewMediator extends SystemUI {
}
mStatusBarKeyguardViewManager.hide(startTime, fadeoutDuration);
mShowing = false;
setShowing(false);
resetKeyguardDonePendingLocked();
mHideAnimationRun = false;
updateActivityLockScreenState();
@@ -1389,7 +1393,7 @@ public class KeyguardViewMediator extends SystemUI {
synchronized (KeyguardViewMediator.this) {
if (DEBUG) Log.d(TAG, "handleVerifyUnlock");
mStatusBarKeyguardViewManager.verifyUnlock();
mShowing = true;
setShowing(true);
updateActivityLockScreenState();
}
}
@@ -1471,4 +1475,12 @@ public class KeyguardViewMediator extends SystemUI {
this.fadeoutDuration = fadeoutDuration;
}
}
private void setShowing(boolean showing) {
boolean changed = (showing != mShowing);
mShowing = showing;
if (changed) {
mTrustManager.reportKeyguardShowingChanged();
}
}
}

View File

@@ -232,6 +232,12 @@ public class TrustAgentWrapper {
mTrustManagerService.mArchive.logAgentConnected(mUserId, name);
setCallback(mCallback);
updateDevicePolicyFeatures();
if (mTrustManagerService.isDeviceLockedInner(mUserId)) {
onDeviceLocked();
} else {
onDeviceUnlocked();
}
}
@Override
@@ -287,6 +293,7 @@ public class TrustAgentWrapper {
onError(e);
}
}
/**
* @see android.service.trust.TrustAgentService#onUnlockAttempt(boolean)
*/
@@ -298,6 +305,28 @@ public class TrustAgentWrapper {
}
}
/**
* @see android.service.trust.TrustAgentService#onDeviceLocked()
*/
public void onDeviceLocked() {
try {
if (mTrustAgentService != null) mTrustAgentService.onDeviceLocked();
} catch (RemoteException e) {
onError(e);
}
}
/**
* @see android.service.trust.TrustAgentService#onDeviceUnlocked()
*/
public void onDeviceUnlocked() {
try {
if (mTrustAgentService != null) mTrustAgentService.onDeviceUnlocked();
} catch (RemoteException e) {
onError(e);
}
}
private void setCallback(ITrustAgentServiceCallback callback) {
try {
if (mTrustAgentService != null) {

View File

@@ -26,7 +26,6 @@ import org.xmlpull.v1.XmlPullParserException;
import android.Manifest;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.admin.DevicePolicyManager;
import android.app.trust.ITrustListener;
import android.app.trust.ITrustManager;
@@ -61,8 +60,8 @@ import android.util.Log;
import android.util.Slog;
import android.util.SparseBooleanArray;
import android.util.Xml;
import android.view.IWindowManager;
import android.view.WindowManagerGlobal;
import android.view.WindowManagerInternal;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -98,6 +97,10 @@ public class TrustManagerService extends SystemService {
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>();
@@ -112,7 +115,11 @@ public class TrustManagerService extends SystemService {
@GuardedBy("mUserIsTrusted")
private final SparseBooleanArray mUserIsTrusted = new SparseBooleanArray();
@GuardedBy("mDeviceLockedForUser")
private final SparseBooleanArray mDeviceLockedForUser = new SparseBooleanArray();
private boolean mTrustAgentsCanRun = false;
private int mCurrentUser = UserHandle.USER_OWNER;
public TrustManagerService(Context context) {
super(context);
@@ -179,10 +186,15 @@ public class TrustManagerService extends SystemService {
public void updateTrust(int userId, boolean initiatedByUser) {
dispatchOnTrustManagedChanged(aggregateIsTrustManaged(userId), userId);
boolean trusted = aggregateIsTrusted(userId);
boolean changed;
synchronized (mUserIsTrusted) {
changed = mUserIsTrusted.get(userId) != trusted;
mUserIsTrusted.put(userId, trusted);
}
dispatchOnTrustChanged(trusted, userId, initiatedByUser);
if (changed) {
refreshDeviceLockedForUser(userId);
}
}
void refreshAgentList(int userId) {
@@ -214,8 +226,7 @@ public class TrustManagerService extends SystemService {
|| userInfo.guestToRemove) continue;
if (!userInfo.supportsSwitchTo()) continue;
if (!mActivityManager.isUserRunning(userInfo.id)) continue;
if (lockPatternUtils.getKeyguardStoredPasswordQuality(userInfo.id)
== DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) continue;
if (!lockPatternUtils.isSecure(userInfo.id)) continue;
if (!mUserHasAuthenticatedSinceBoot.get(userInfo.id)) continue;
DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
@@ -275,6 +286,73 @@ public class TrustManagerService extends SystemService {
}
}
boolean isDeviceLockedInner(int userId) {
synchronized (mDeviceLockedForUser) {
return mDeviceLockedForUser.get(userId, true);
}
}
private void refreshDeviceLockedForUser(int userId) {
if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_OWNER) {
Log.e(TAG, "refreshAgentList(userId=" + userId + "): Invalid user handle,"
+ " must be USER_ALL or a specific user.", new Throwable("here"));
userId = UserHandle.USER_ALL;
}
List<UserInfo> userInfos;
if (userId == UserHandle.USER_ALL) {
userInfos = mUserManager.getUsers(true /* excludeDying */);
} else {
userInfos = new ArrayList<>();
userInfos.add(mUserManager.getUserInfo(userId));
}
IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
for (int i = 0; i < userInfos.size(); i++) {
UserInfo info = userInfos.get(i);
if (info == null || info.partial || !info.isEnabled() || info.guestToRemove
|| !info.supportsSwitchTo()) {
continue;
}
int id = info.id;
boolean secure = mLockPatternUtils.isSecure(id);
boolean trusted = aggregateIsTrusted(id);
boolean showingKeyguard = true;
if (mCurrentUser == id) {
try {
showingKeyguard = wm.isKeyguardLocked();
} catch (RemoteException e) {
}
}
boolean deviceLocked = secure && showingKeyguard && !trusted;
boolean changed;
synchronized (mDeviceLockedForUser) {
changed = isDeviceLockedInner(id) != deviceLocked;
mDeviceLockedForUser.put(id, deviceLocked);
}
if (changed) {
dispatchDeviceLocked(id, deviceLocked);
}
}
}
private void dispatchDeviceLocked(int userId, boolean isLocked) {
for (int i = 0; i < mActiveAgents.size(); i++) {
AgentInfo agent = mActiveAgents.valueAt(i);
if (agent.userId == userId) {
if (isLocked) {
agent.agent.onDeviceLocked();
} else{
agent.agent.onDeviceUnlocked();
}
}
}
}
void updateDevicePolicyFeatures() {
for (int i = 0; i < mActiveAgents.size(); i++) {
AgentInfo info = mActiveAgents.valueAt(i);
@@ -542,12 +620,17 @@ public class TrustManagerService extends SystemService {
@Override
public void onStartUser(int userId) {
refreshAgentList(userId);
mHandler.obtainMessage(MSG_START_USER, userId, 0, null).sendToTarget();
}
@Override
public void onCleanupUser(int userId) {
refreshAgentList(userId);
mHandler.obtainMessage(MSG_CLEANUP_USER, userId, 0, null).sendToTarget();
}
@Override
public void onSwitchUser(int userId) {
mHandler.obtainMessage(MSG_SWITCH_USER, userId, 0, null).sendToTarget();
}
// Plumbing
@@ -579,6 +662,14 @@ public class TrustManagerService extends SystemService {
}
}
@Override
public void reportKeyguardShowingChanged() throws RemoteException {
enforceReportPermission();
// coalesce refresh messages.
mHandler.removeMessages(MSG_KEYGUARD_SHOWING_CHANGED);
mHandler.sendEmptyMessage(MSG_KEYGUARD_SHOWING_CHANGED);
}
@Override
public void registerTrustListener(ITrustListener trustListener) throws RemoteException {
enforceListenerPermission();
@@ -597,21 +688,7 @@ public class TrustManagerService extends SystemService {
false /* allowAll */, true /* requireFull */, "isDeviceLocked", null);
userId = resolveProfileParent(userId);
boolean isSecure = mLockPatternUtils.isSecure(userId);
boolean isTrusted;
synchronized (mUserIsTrusted) {
isTrusted = mUserIsTrusted.get(userId);
}
boolean isLocked;
if (ActivityManager.getCurrentUser() != userId) {
isLocked = true;
} else {
isLocked = WindowManagerGlobal.getWindowManagerService().isKeyguardLocked();
}
return isSecure && isLocked && !isTrusted;
return isDeviceLockedInner(userId);
}
private void enforceReportPermission() {
@@ -636,19 +713,13 @@ public class TrustManagerService extends SystemService {
fout.println("disabled because the third-party apps can't run yet.");
return;
}
final UserInfo currentUser;
final List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
try {
currentUser = ActivityManagerNative.getDefault().getCurrentUser();
} catch (RemoteException e) {
throw new RuntimeException(e);
}
mHandler.runWithScissors(new Runnable() {
@Override
public void run() {
fout.println("Trust manager state:");
for (UserInfo user : userInfos) {
dumpUser(fout, user, user.id == currentUser.id);
dumpUser(fout, user, user.id == mCurrentUser);
}
}
}, 1500);
@@ -657,11 +728,17 @@ public class TrustManagerService extends SystemService {
private void dumpUser(PrintWriter fout, UserInfo user, boolean isCurrent) {
fout.printf(" User \"%s\" (id=%d, flags=%#x)",
user.name, user.id, user.flags);
if (!user.supportsSwitchTo()) {
fout.println("(managed profile)");
fout.println(" disabled because switching to this user is not possible.");
return;
}
if (isCurrent) {
fout.print(" (current)");
}
fout.print(": trusted=" + dumpBool(aggregateIsTrusted(user.id)));
fout.print(", trustManaged=" + dumpBool(aggregateIsTrustManaged(user.id)));
fout.print(", deviceLocked=" + dumpBool(isDeviceLockedInner(user.id)));
fout.println();
fout.println(" Enabled agents:");
boolean duplicateSimpleNames = false;
@@ -726,10 +803,23 @@ public class TrustManagerService extends SystemService {
break;
case MSG_ENABLED_AGENTS_CHANGED:
refreshAgentList(UserHandle.USER_ALL);
// 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(UserHandle.USER_CURRENT);
break;
case MSG_START_USER:
case MSG_CLEANUP_USER:
refreshAgentList(msg.arg1);
break;
case MSG_SWITCH_USER:
mCurrentUser = msg.arg1;
refreshDeviceLockedForUser(UserHandle.USER_ALL);
break;
}
}
};
@@ -771,8 +861,14 @@ public class TrustManagerService extends SystemService {
int userId = getUserId(intent);
if (userId > 0) {
mUserHasAuthenticatedSinceBoot.delete(userId);
mUserIsTrusted.delete(userId);
synchronized (mUserIsTrusted) {
mUserIsTrusted.delete(userId);
}
synchronized (mDeviceLockedForUser) {
mDeviceLockedForUser.delete(userId);
}
refreshAgentList(userId);
refreshDeviceLockedForUser(userId);
}
}
}