diff options
author | Jim Miller <jaggies@google.com> | 2014-08-14 18:02:45 -0700 |
---|---|---|
committer | Jim Miller <jaggies@google.com> | 2014-08-22 22:43:30 +0000 |
commit | d4efaac5d54cdb3735b032bb76a5639949f33216 (patch) | |
tree | 74b853dfc837f935c60c1966e2bf2302d48c0871 | |
parent | 7653a30ea0232ab8323ec51ddcba8d8054ca8a2f (diff) | |
download | frameworks_base-d4efaac5d54cdb3735b032bb76a5639949f33216.zip frameworks_base-d4efaac5d54cdb3735b032bb76a5639949f33216.tar.gz frameworks_base-d4efaac5d54cdb3735b032bb76a5639949f33216.tar.bz2 |
Update TrustAgentService API after review.
Also documents timebase on related DevicePolicyManager API.
Fixes bugs 16401527 and 17046034
Change-Id: I8ee6d0055ab6f52ec71630344d3232f7875d9c1d
5 files changed, 101 insertions, 16 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 0dc8f66..41bbb87 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1373,6 +1373,8 @@ public class DevicePolicyManager { * and its profiles or a particular one. * @param admin The name of the admin component to check, or null to aggregate * all admins. + * @return time in milliseconds for the given admin or the minimum value (strictest) of + * all admins if admin is null. */ public long getMaximumTimeToLock(ComponentName admin) { return getMaximumTimeToLock(admin, UserHandle.myUserId()); diff --git a/core/java/android/service/trust/ITrustAgentService.aidl b/core/java/android/service/trust/ITrustAgentService.aidl index 637d080..bd80a3f 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 onTrustTimeout(); oneway void setCallback(ITrustAgentServiceCallback callback); oneway void setTrustAgentFeaturesEnabled(in Bundle options, IBinder token); } diff --git a/core/java/android/service/trust/TrustAgentService.java b/core/java/android/service/trust/TrustAgentService.java index 5fe9194..337ae60 100644 --- a/core/java/android/service/trust/TrustAgentService.java +++ b/core/java/android/service/trust/TrustAgentService.java @@ -30,6 +30,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.RemoteException; +import android.os.SystemClock; import android.util.Log; import android.util.Slog; @@ -37,7 +38,10 @@ import android.util.Slog; * A service that notifies the system about whether it believes the environment of the device * to be trusted. * - * <p>Trust agents may only be provided by the platform.</p> + * <p>Trust agents may only be provided by the platform. It is expected that there is only + * one trust agent installed on the platform. In the event there is more than one, + * either trust agent can enable trust. + * </p> * * <p>To extend this class, you must declare the service in your manifest file with * the {@link android.Manifest.permission#BIND_TRUST_AGENT} permission @@ -90,6 +94,7 @@ public class TrustAgentService extends Service { private static final int MSG_UNLOCK_ATTEMPT = 1; private static final int MSG_SET_TRUST_AGENT_FEATURES_ENABLED = 2; + private static final int MSG_TRUST_TIMEOUT = 3; private ITrustAgentServiceCallback mCallback; @@ -118,6 +123,9 @@ public class TrustAgentService extends Service { onError("calling onSetTrustAgentFeaturesEnabledCompleted()"); } break; + case MSG_TRUST_TIMEOUT: + onTrustTimeout(); + break; } } }; @@ -139,21 +147,32 @@ public class TrustAgentService extends Service { } /** - * Called when the user attempted to authenticate on the device. + * Called after the user attempts to authenticate in keyguard with their device credentials, + * such as pin, pattern or password. * - * @param successful true if the attempt succeeded + * @param successful true if the user successfully completed the challenge. */ public void onUnlockAttempt(boolean successful) { } + /** + * Called when the timeout provided by the agent expires. Note that this may be called earlier + * than requested by the agent if the trust timeout is adjusted by the system or + * {@link DevicePolicyManager}. The agent is expected to re-evaluate the trust state and only + * call {@link #grantTrust(CharSequence, long, boolean)} if the trust state should be + * continued. + */ + public void onTrustTimeout() { + } + private void onError(String msg) { Slog.v(TAG, "Remote exception while " + msg); } /** - * Called when device policy wants to restrict features in the TrustAgent in response to + * Called when device policy wants to restrict features in the agent in response to * {@link DevicePolicyManager#setTrustAgentFeaturesEnabled(ComponentName, ComponentName, java.util.List) }. - * TrustAgents that support this feature should overload this method and return 'true'. + * Agents that support this feature should overload this method and return 'true'. * * The list of options can be obtained by calling * options.getStringArrayList({@link #KEY_FEATURES}). Presence of a feature string in the list @@ -174,10 +193,19 @@ public class TrustAgentService extends Service { * Call to grant trust on the device. * * @param message describes why the device is trusted, e.g. "Trusted by location". - * @param durationMs amount of time in milliseconds to keep the device in a trusted state. Trust - * for this agent will automatically be revoked when the timeout expires. - * @param initiatedByUser indicates that the user has explicitly initiated an action that proves - * the user is about to use the device. + * @param durationMs amount of time in milliseconds to keep the device in a trusted state. + * Trust for this agent will automatically be revoked when the timeout expires unless + * extended by a subsequent call to this function. The timeout is measured from the + * invocation of this function as dictated by {@link SystemClock#elapsedRealtime())}. + * For security reasons, the value should be no larger than necessary. + * The value may be adjusted by the system as necessary to comply with a policy controlled + * by the system or {@link DevicePolicyManager} restrictions. See {@link #onTrustTimeout()} + * for determining when trust expires. + * @param initiatedByUser this is a hint to the system that trust is being granted as the + * direct result of user action - such as solving a security challenge. The hint is used + * by the system to optimize the experience. Behavior may vary by device and release, so + * one should only set this parameter if it meets the above criteria rather than relying on + * the behavior of any particular device or release. * @throws IllegalStateException if the agent is not currently managing trust. */ public final void grantTrust( @@ -254,13 +282,17 @@ public class TrustAgentService extends Service { } private final class TrustAgentServiceWrapper extends ITrustAgentService.Stub { - @Override + @Override /* Binder API */ public void onUnlockAttempt(boolean successful) { - mHandler.obtainMessage(MSG_UNLOCK_ATTEMPT, successful ? 1 : 0, 0) - .sendToTarget(); + mHandler.obtainMessage(MSG_UNLOCK_ATTEMPT, successful ? 1 : 0, 0).sendToTarget(); + } + + @Override /* Binder API */ + public void onTrustTimeout() { + mHandler.sendEmptyMessage(MSG_TRUST_TIMEOUT); } - @Override + @Override /* Binder API */ public void setCallback(ITrustAgentServiceCallback callback) { synchronized (mLock) { mCallback = callback; @@ -280,7 +312,7 @@ public class TrustAgentService extends Service { } } - @Override + @Override /* Binder API */ public void setTrustAgentFeaturesEnabled(Bundle features, IBinder token) { Message msg = mHandler.obtainMessage(MSG_SET_TRUST_AGENT_FEATURES_ENABLED, token); msg.setData(features); diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java index 4ea1c77..c650a0f 100644 --- a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java +++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java @@ -76,6 +76,12 @@ public class SampleTrustAgent extends TrustAgentService } @Override + public void onTrustTimeout() { + super.onTrustTimeout(); + Toast.makeText(this, "onTrustTimeout(): timeout expired", Toast.LENGTH_SHORT).show(); + } + + @Override public void onUnlockAttempt(boolean successful) { if (getReportUnlockAttempts(this)) { Toast.makeText(this, "onUnlockAttempt(successful=" + successful + ")", diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java index 0523af7..4c080cb 100644 --- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java +++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java @@ -16,16 +16,22 @@ package com.android.server.trust; +import android.app.AlarmManager; +import android.app.PendingIntent; import android.app.admin.DevicePolicyManager; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.ServiceConnection; +import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; +import android.os.PatternMatcher; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; @@ -43,6 +49,9 @@ import java.util.List; * TrustManager and the actual TrustAgent. */ public class TrustAgentWrapper { + private static final String EXTRA_COMPONENT_NAME = "componentName"; + private static final String TRUST_EXPIRED_ACTION = "android.server.trust.TRUST_EXPIRED_ACTION"; + private static final String PERMISSION = "android.permission.PROVIDE_TRUST_AGENT"; private static final boolean DEBUG = false; private static final String TAG = "TrustAgentWrapper"; @@ -79,6 +88,20 @@ public class TrustAgentWrapper { private boolean mTrustDisabledByDpm; private boolean mManagingTrust; private IBinder mSetTrustAgentFeaturesToken; + private AlarmManager mAlarmManager; + private final Intent mAlarmIntent; + + private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + ComponentName component = intent.getParcelableExtra(EXTRA_COMPONENT_NAME); + if (TRUST_EXPIRED_ACTION.equals(intent.getAction()) + && mName.equals(component)) { + mHandler.removeMessages(MSG_TRUST_TIMEOUT); + mHandler.sendEmptyMessage(MSG_TRUST_TIMEOUT); + } + } + }; private final Handler mHandler = new Handler() { @Override @@ -95,8 +118,10 @@ public class TrustAgentWrapper { boolean initiatedByUser = msg.arg1 != 0; long durationMs = msg.getData().getLong(DATA_DURATION); if (durationMs > 0) { - mHandler.removeMessages(MSG_TRUST_TIMEOUT); - mHandler.sendEmptyMessageDelayed(MSG_TRUST_TIMEOUT, durationMs); + long expiration = SystemClock.elapsedRealtime() + durationMs; + PendingIntent op = PendingIntent.getBroadcast(mContext, 0, mAlarmIntent, + PendingIntent.FLAG_CANCEL_CURRENT); + mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, expiration, op); } mTrustManagerService.mArchive.logGrantTrust(mUserId, mName, (mMessage != null ? mMessage.toString() : null), @@ -106,6 +131,7 @@ public class TrustAgentWrapper { case MSG_TRUST_TIMEOUT: if (DEBUG) Slog.v(TAG, "Trust timed out : " + mName.flattenToShortString()); mTrustManagerService.mArchive.logTrustTimeout(mUserId, mName); + onTrustTimeout(); // Fall through. case MSG_REVOKE_TRUST: mTrusted = false; @@ -212,8 +238,19 @@ public class TrustAgentWrapper { Intent intent, UserHandle user) { mContext = context; mTrustManagerService = trustManagerService; + mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); mUserId = user.getIdentifier(); mName = intent.getComponent(); + + mAlarmIntent = new Intent(TRUST_EXPIRED_ACTION).putExtra(EXTRA_COMPONENT_NAME, mName); + mAlarmIntent.setData(Uri.parse(mAlarmIntent.toUri(Intent.URI_INTENT_SCHEME))); + + final IntentFilter alarmFilter = new IntentFilter(TRUST_EXPIRED_ACTION); + alarmFilter.addDataScheme(mAlarmIntent.getScheme()); + final String pathUri = mAlarmIntent.toUri(Intent.URI_INTENT_SCHEME); + alarmFilter.addDataPath(pathUri, PatternMatcher.PATTERN_LITERAL); + mContext.registerReceiver(mBroadcastReceiver, alarmFilter); + // Schedules a restart for when connecting times out. If the connection succeeds, // the restart is canceled in mCallback's onConnected. scheduleRestart(); @@ -227,6 +264,13 @@ public class TrustAgentWrapper { Slog.w(TAG , "Remote Exception", e); } + private void onTrustTimeout() { + try { + if (mTrustAgentService != null) mTrustAgentService.onTrustTimeout(); + } catch (RemoteException e) { + onError(e); + } + } /** * @see android.service.trust.TrustAgentService#onUnlockAttempt(boolean) */ |