/** * Copyright (C) 2014 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.service.trust; import android.Manifest; import android.annotation.IntDef; import android.annotation.SdkConstant; import android.annotation.SystemApi; import android.app.Service; import android.app.admin.DevicePolicyManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.PersistableBundle; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.util.Log; import android.util.Slog; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; /** * A service that notifies the system about whether it believes the environment of the device * to be trusted. * *
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. *
* *To extend this class, you must declare the service in your manifest file with * the {@link android.Manifest.permission#BIND_TRUST_AGENT} permission * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:
** <service android:name=".TrustAgent" * android:label="@string/service_name" * android:permission="android.permission.BIND_TRUST_AGENT"> * <intent-filter> * <action android:name="android.service.trust.TrustAgentService" /> * </intent-filter> * <meta-data android:name="android.service.trust.trustagent" * android:value="@xml/trust_agent" /> * </service>* *
The associated meta-data file can specify an activity that is accessible through Settings * and should allow configuring the trust agent, as defined in * {@link android.R.styleable#TrustAgent}. For example:
* ** <trust-agent xmlns:android="http://schemas.android.com/apk/res/android" * android:settingsActivity=".TrustAgentSettings" />* * @hide */ @SystemApi public class TrustAgentService extends Service { private final String TAG = TrustAgentService.class.getSimpleName() + "[" + getClass().getSimpleName() + "]"; private static final boolean DEBUG = false; /** * The {@link Intent} that must be declared as handled by the service. */ @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) public static final String SERVICE_INTERFACE = "android.service.trust.TrustAgentService"; /** * The name of the {@code meta-data} tag pointing to additional configuration of the trust * agent. */ public static final String TRUST_AGENT_META_DATA = "android.service.trust.trustagent"; /** * Flag for {@link #grantTrust(CharSequence, long, int)} indicating 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. */ public static final int FLAG_GRANT_TRUST_INITIATED_BY_USER = 1 << 0; /** * Flag for {@link #grantTrust(CharSequence, long, int)} indicating that the agent would like * to dismiss the keyguard. When using this flag, the {@code TrustAgentService} must ensure * it is only set in response to a direct user action with the expectation of dismissing the * keyguard. */ public static final int FLAG_GRANT_TRUST_DISMISS_KEYGUARD = 1 << 1; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(flag = true, value = { FLAG_GRANT_TRUST_INITIATED_BY_USER, FLAG_GRANT_TRUST_DISMISS_KEYGUARD, }) public @interface GrantTrustFlags {} /** * Int enum indicating that escrow token is active. * See {@link #onEscrowTokenStateReceived(long, int)} * */ public static final int TOKEN_STATE_ACTIVE = 1; /** * Int enum indicating that escow token is inactive. * See {@link #onEscrowTokenStateReceived(long, int)} * */ public static final int TOKEN_STATE_INACTIVE = 0; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(flag = true, value = { TOKEN_STATE_ACTIVE, TOKEN_STATE_INACTIVE, }) public @interface TokenState {} 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; private static final int MSG_UNLOCK_LOCKOUT = 6; private static final int MSG_ESCROW_TOKEN_ADDED = 7; private static final int MSG_ESCROW_TOKEN_STATE_RECEIVED = 8; private static final int MSG_ESCROW_TOKEN_REMOVED = 9; private static final String EXTRA_TOKEN = "token"; private static final String EXTRA_TOKEN_HANDLE = "token_handle"; private static final String EXTRA_USER_HANDLE = "user_handle"; private static final String EXTRA_TOKEN_STATE = "token_state"; private static final String EXTRA_TOKEN_REMOVED_RESULT = "token_removed_result"; /** * Class containing raw data for a given configuration request. */ private static final class ConfigurationData { final IBinder token; final List
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) { } /** * Called when an escrow token is added for user userId. * * @param token the added token * @param handle the handle to the corresponding internal synthetic password. A user is unlocked * by presenting both handle and escrow token. * @param user the user to which the escrow token is added. * */ public void onEscrowTokenAdded(byte[] token, long handle, UserHandle user) { } /** * Called when an escrow token state is received upon request. * * @param handle the handle to the internal synthetic password. * @param state the state of the requested escrow token, see {@link TokenState}. * */ public void onEscrowTokenStateReceived(long handle, @TokenState int tokenState) { } /** * Called when an escrow token is removed. * * @param handle the handle to the removed the synthetic password. * @param successful whether the removing operaiton is achieved. * */ public void onEscrowTokenRemoved(long handle, boolean successful) { } private void onError(String msg) { Slog.v(TAG, "Remote exception while " + msg); } /** * Called when device policy admin wants to enable specific options for agent in response to * {@link DevicePolicyManager#setKeyguardDisabledFeatures(ComponentName, int)} and * {@link DevicePolicyManager#setTrustAgentConfiguration(ComponentName, ComponentName, * PersistableBundle)}. *
Agents that support configuration options should overload this method and return 'true'.
*
* @param options The aggregated list of options or an empty list if no restrictions apply.
* @return true if it supports configuration options.
*/
public boolean onConfigure(List