TrustAgentService.java revision a06d5ca1d96af3555ad4e384994e6321a0c5bb9c
1/** 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.service.trust; 18 19import android.Manifest; 20import android.annotation.SdkConstant; 21import android.annotation.SystemApi; 22import android.app.Service; 23import android.app.admin.DevicePolicyManager; 24import android.content.ComponentName; 25import android.content.Intent; 26import android.content.pm.PackageManager; 27import android.content.pm.ServiceInfo; 28import android.os.Bundle; 29import android.os.Handler; 30import android.os.IBinder; 31import android.os.RemoteException; 32import android.util.Log; 33import android.util.Slog; 34 35/** 36 * A service that notifies the system about whether it believes the environment of the device 37 * to be trusted. 38 * 39 * <p>Trust agents may only be provided by the platform.</p> 40 * 41 * <p>To extend this class, you must declare the service in your manifest file with 42 * the {@link android.Manifest.permission#BIND_TRUST_AGENT} permission 43 * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p> 44 * <pre> 45 * <service android:name=".TrustAgent" 46 * android:label="@string/service_name" 47 * android:permission="android.permission.BIND_TRUST_AGENT"> 48 * <intent-filter> 49 * <action android:name="android.service.trust.TrustAgentService" /> 50 * </intent-filter> 51 * <meta-data android:name="android.service.trust.trustagent" 52 * android:value="@xml/trust_agent" /> 53 * </service></pre> 54 * 55 * <p>The associated meta-data file can specify an activity that is accessible through Settings 56 * and should allow configuring the trust agent, as defined in 57 * {@link android.R.styleable#TrustAgent}. For example:</p> 58 * 59 * <pre> 60 * <trust-agent xmlns:android="http://schemas.android.com/apk/res/android" 61 * android:settingsActivity=".TrustAgentSettings" /></pre> 62 * 63 * @hide 64 */ 65@SystemApi 66public class TrustAgentService extends Service { 67 private final String TAG = TrustAgentService.class.getSimpleName() + 68 "[" + getClass().getSimpleName() + "]"; 69 70 /** 71 * The {@link Intent} that must be declared as handled by the service. 72 */ 73 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) 74 public static final String SERVICE_INTERFACE 75 = "android.service.trust.TrustAgentService"; 76 77 /** 78 * The name of the {@code meta-data} tag pointing to additional configuration of the trust 79 * agent. 80 */ 81 public static final String TRUST_AGENT_META_DATA = "android.service.trust.trustagent"; 82 83 /** 84 * A white list of features that the given trust agent should support when otherwise disabled 85 * by device policy. 86 */ 87 public static final String KEY_FEATURES = "trust_agent_features"; 88 89 private static final int MSG_UNLOCK_ATTEMPT = 1; 90 91 private static final boolean DEBUG = false; 92 93 private ITrustAgentServiceCallback mCallback; 94 95 private Runnable mPendingGrantTrustTask; 96 97 // Lock used to access mPendingGrantTrustTask and mCallback. 98 private final Object mLock = new Object(); 99 100 private Handler mHandler = new Handler() { 101 public void handleMessage(android.os.Message msg) { 102 switch (msg.what) { 103 case MSG_UNLOCK_ATTEMPT: 104 onUnlockAttempt(msg.arg1 != 0); 105 break; 106 } 107 }; 108 }; 109 110 @Override 111 public void onCreate() { 112 super.onCreate(); 113 ComponentName component = new ComponentName(this, getClass()); 114 try { 115 ServiceInfo serviceInfo = getPackageManager().getServiceInfo(component, 0 /* flags */); 116 if (!Manifest.permission.BIND_TRUST_AGENT.equals(serviceInfo.permission)) { 117 throw new IllegalStateException(component.flattenToShortString() 118 + " is not declared with the permission " 119 + "\"" + Manifest.permission.BIND_TRUST_AGENT + "\""); 120 } 121 } catch (PackageManager.NameNotFoundException e) { 122 Log.e(TAG, "Can't get ServiceInfo for " + component.toShortString()); 123 } 124 } 125 126 /** 127 * Called when the user attempted to authenticate on the device. 128 * 129 * @param successful true if the attempt succeeded 130 */ 131 public void onUnlockAttempt(boolean successful) { 132 } 133 134 private void onError(String msg) { 135 Slog.v(TAG, "Remote exception while " + msg); 136 } 137 138 /** 139 * Called when device policy wants to restrict features in the TrustAgent in response to 140 * {@link DevicePolicyManager#setTrustAgentFeaturesEnabled(ComponentName, ComponentName, java.util.List) }. 141 * TrustAgents that support this feature should overload this method and return 'true'. 142 * 143 * The list of options can be obtained by calling 144 * options.getStringArrayList({@link #KEY_FEATURES}). Presence of a feature string in the list 145 * means it should be enabled ("white-listed"). Absence of the feature means it should be 146 * disabled. An empty list means all features should be disabled. 147 * 148 * This function is only called if {@link DevicePolicyManager#KEYGUARD_DISABLE_TRUST_AGENTS} is 149 * set. 150 * 151 * @param options Option feature bundle. 152 * @return true if the {@link #TrustAgentService()} supports this feature. 153 */ 154 public boolean onSetTrustAgentFeaturesEnabled(Bundle options) { 155 return false; 156 } 157 158 /** 159 * Call to grant trust on the device. 160 * 161 * @param message describes why the device is trusted, e.g. "Trusted by location". 162 * @param durationMs amount of time in milliseconds to keep the device in a trusted state. Trust 163 * for this agent will automatically be revoked when the timeout expires. 164 * @param initiatedByUser indicates that the user has explicitly initiated an action that proves 165 * the user is about to use the device. 166 */ 167 public final void grantTrust( 168 final CharSequence message, final long durationMs, final boolean initiatedByUser) { 169 synchronized (mLock) { 170 if (mCallback != null) { 171 try { 172 mCallback.grantTrust(message.toString(), durationMs, initiatedByUser); 173 } catch (RemoteException e) { 174 onError("calling enableTrust()"); 175 } 176 } else { 177 // Remember trust has been granted so we can effectively grant it once the service 178 // is bound. 179 mPendingGrantTrustTask = new Runnable() { 180 @Override 181 public void run() { 182 grantTrust(message, durationMs, initiatedByUser); 183 } 184 }; 185 } 186 } 187 } 188 189 /** 190 * Call to revoke trust on the device. 191 */ 192 public final void revokeTrust() { 193 synchronized (mLock) { 194 if (mPendingGrantTrustTask != null) { 195 mPendingGrantTrustTask = null; 196 } 197 if (mCallback != null) { 198 try { 199 mCallback.revokeTrust(); 200 } catch (RemoteException e) { 201 onError("calling revokeTrust()"); 202 } 203 } 204 } 205 } 206 207 @Override 208 public final IBinder onBind(Intent intent) { 209 if (DEBUG) Slog.v(TAG, "onBind() intent = " + intent); 210 return new TrustAgentServiceWrapper(); 211 } 212 213 private final class TrustAgentServiceWrapper extends ITrustAgentService.Stub { 214 @Override 215 public void onUnlockAttempt(boolean successful) { 216 mHandler.obtainMessage(MSG_UNLOCK_ATTEMPT, successful ? 1 : 0, 0) 217 .sendToTarget(); 218 } 219 220 @Override 221 public void setCallback(ITrustAgentServiceCallback callback) { 222 synchronized (mLock) { 223 mCallback = callback; 224 if (mPendingGrantTrustTask != null) { 225 mPendingGrantTrustTask.run(); 226 mPendingGrantTrustTask = null; 227 } 228 } 229 } 230 231 @Override 232 public boolean setTrustAgentFeaturesEnabled(Bundle features) { 233 synchronized (mLock) { 234 return onSetTrustAgentFeaturesEnabled(features); 235 } 236 } 237 } 238 239} 240