TrustAgentService.java revision a43fd03b9b23f9ad0deae9ee69ee80aaa1433cdb
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.Handler; 29import android.os.IBinder; 30import android.os.PersistableBundle; 31import android.os.RemoteException; 32import android.util.Log; 33import android.util.Slog; 34 35import java.util.List; 36 37/** 38 * A service that notifies the system about whether it believes the environment of the device 39 * to be trusted. 40 * 41 * <p>Trust agents may only be provided by the platform. It is expected that there is only 42 * one trust agent installed on the platform. In the event there is more than one, 43 * either trust agent can enable trust. 44 * </p> 45 * 46 * <p>To extend this class, you must declare the service in your manifest file with 47 * the {@link android.Manifest.permission#BIND_TRUST_AGENT} permission 48 * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p> 49 * <pre> 50 * <service android:name=".TrustAgent" 51 * android:label="@string/service_name" 52 * android:permission="android.permission.BIND_TRUST_AGENT"> 53 * <intent-filter> 54 * <action android:name="android.service.trust.TrustAgentService" /> 55 * </intent-filter> 56 * <meta-data android:name="android.service.trust.trustagent" 57 * android:value="@xml/trust_agent" /> 58 * </service></pre> 59 * 60 * <p>The associated meta-data file can specify an activity that is accessible through Settings 61 * and should allow configuring the trust agent, as defined in 62 * {@link android.R.styleable#TrustAgent}. For example:</p> 63 * 64 * <pre> 65 * <trust-agent xmlns:android="http://schemas.android.com/apk/res/android" 66 * android:settingsActivity=".TrustAgentSettings" /></pre> 67 * 68 * @hide 69 */ 70@SystemApi 71public class TrustAgentService extends Service { 72 private final String TAG = TrustAgentService.class.getSimpleName() + 73 "[" + getClass().getSimpleName() + "]"; 74 private static final boolean DEBUG = false; 75 76 /** 77 * The {@link Intent} that must be declared as handled by the service. 78 */ 79 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) 80 public static final String SERVICE_INTERFACE 81 = "android.service.trust.TrustAgentService"; 82 83 /** 84 * The name of the {@code meta-data} tag pointing to additional configuration of the trust 85 * agent. 86 */ 87 public static final String TRUST_AGENT_META_DATA = "android.service.trust.trustagent"; 88 89 private static final int MSG_UNLOCK_ATTEMPT = 1; 90 private static final int MSG_CONFIGURE = 2; 91 private static final int MSG_TRUST_TIMEOUT = 3; 92 private static final int MSG_DEVICE_LOCKED = 4; 93 private static final int MSG_DEVICE_UNLOCKED = 5; 94 95 /** 96 * Class containing raw data for a given configuration request. 97 */ 98 private static final class ConfigurationData { 99 final IBinder token; 100 final List<PersistableBundle> options; 101 ConfigurationData(List<PersistableBundle> opts, IBinder t) { 102 options = opts; 103 token = t; 104 } 105 } 106 107 private ITrustAgentServiceCallback mCallback; 108 109 private Runnable mPendingGrantTrustTask; 110 111 private boolean mManagingTrust; 112 113 // Lock used to access mPendingGrantTrustTask and mCallback. 114 private final Object mLock = new Object(); 115 116 private Handler mHandler = new Handler() { 117 public void handleMessage(android.os.Message msg) { 118 switch (msg.what) { 119 case MSG_UNLOCK_ATTEMPT: 120 onUnlockAttempt(msg.arg1 != 0); 121 break; 122 case MSG_CONFIGURE: 123 ConfigurationData data = (ConfigurationData) msg.obj; 124 boolean result = onConfigure(data.options); 125 if (data.token != null) { 126 try { 127 synchronized (mLock) { 128 mCallback.onConfigureCompleted(result, data.token); 129 } 130 } catch (RemoteException e) { 131 onError("calling onSetTrustAgentFeaturesEnabledCompleted()"); 132 } 133 } 134 break; 135 case MSG_TRUST_TIMEOUT: 136 onTrustTimeout(); 137 break; 138 case MSG_DEVICE_LOCKED: 139 onDeviceLocked(); 140 break; 141 case MSG_DEVICE_UNLOCKED: 142 onDeviceUnlocked(); 143 break; 144 } 145 } 146 }; 147 148 @Override 149 public void onCreate() { 150 super.onCreate(); 151 ComponentName component = new ComponentName(this, getClass()); 152 try { 153 ServiceInfo serviceInfo = getPackageManager().getServiceInfo(component, 0 /* flags */); 154 if (!Manifest.permission.BIND_TRUST_AGENT.equals(serviceInfo.permission)) { 155 throw new IllegalStateException(component.flattenToShortString() 156 + " is not declared with the permission " 157 + "\"" + Manifest.permission.BIND_TRUST_AGENT + "\""); 158 } 159 } catch (PackageManager.NameNotFoundException e) { 160 Log.e(TAG, "Can't get ServiceInfo for " + component.toShortString()); 161 } 162 } 163 164 /** 165 * Called after the user attempts to authenticate in keyguard with their device credentials, 166 * such as pin, pattern or password. 167 * 168 * @param successful true if the user successfully completed the challenge. 169 */ 170 public void onUnlockAttempt(boolean successful) { 171 } 172 173 /** 174 * Called when the timeout provided by the agent expires. Note that this may be called earlier 175 * than requested by the agent if the trust timeout is adjusted by the system or 176 * {@link DevicePolicyManager}. The agent is expected to re-evaluate the trust state and only 177 * call {@link #grantTrust(CharSequence, long, boolean)} if the trust state should be 178 * continued. 179 */ 180 public void onTrustTimeout() { 181 } 182 183 /** 184 * Called when the device enters a state where a PIN, pattern or 185 * password must be entered to unlock it. 186 */ 187 public void onDeviceLocked() { 188 } 189 190 /** 191 * Called when the device leaves a state where a PIN, pattern or 192 * password must be entered to unlock it. 193 */ 194 public void onDeviceUnlocked() { 195 } 196 197 private void onError(String msg) { 198 Slog.v(TAG, "Remote exception while " + msg); 199 } 200 201 /** 202 * Called when device policy admin wants to enable specific options for agent in response to 203 * {@link DevicePolicyManager#setKeyguardDisabledFeatures(ComponentName, int)} and 204 * {@link DevicePolicyManager#setTrustAgentConfiguration(ComponentName, ComponentName, 205 * PersistableBundle)}. 206 * <p>Agents that support configuration options should overload this method and return 'true'. 207 * 208 * @param options The aggregated list of options or an empty list if no restrictions apply. 209 * @return true if the {@link TrustAgentService} supports configuration options. 210 */ 211 public boolean onConfigure(List<PersistableBundle> options) { 212 return false; 213 } 214 215 /** 216 * Call to grant trust on the device. 217 * 218 * @param message describes why the device is trusted, e.g. "Trusted by location". 219 * @param durationMs amount of time in milliseconds to keep the device in a trusted state. 220 * Trust for this agent will automatically be revoked when the timeout expires unless 221 * extended by a subsequent call to this function. The timeout is measured from the 222 * invocation of this function as dictated by {@link SystemClock#elapsedRealtime())}. 223 * For security reasons, the value should be no larger than necessary. 224 * The value may be adjusted by the system as necessary to comply with a policy controlled 225 * by the system or {@link DevicePolicyManager} restrictions. See {@link #onTrustTimeout()} 226 * for determining when trust expires. 227 * @param initiatedByUser this is a hint to the system that trust is being granted as the 228 * direct result of user action - such as solving a security challenge. The hint is used 229 * by the system to optimize the experience. Behavior may vary by device and release, so 230 * one should only set this parameter if it meets the above criteria rather than relying on 231 * the behavior of any particular device or release. 232 * @throws IllegalStateException if the agent is not currently managing trust. 233 */ 234 public final void grantTrust( 235 final CharSequence message, final long durationMs, final boolean initiatedByUser) { 236 synchronized (mLock) { 237 if (!mManagingTrust) { 238 throw new IllegalStateException("Cannot grant trust if agent is not managing trust." 239 + " Call setManagingTrust(true) first."); 240 } 241 if (mCallback != null) { 242 try { 243 mCallback.grantTrust(message.toString(), durationMs, initiatedByUser); 244 } catch (RemoteException e) { 245 onError("calling enableTrust()"); 246 } 247 } else { 248 // Remember trust has been granted so we can effectively grant it once the service 249 // is bound. 250 mPendingGrantTrustTask = new Runnable() { 251 @Override 252 public void run() { 253 grantTrust(message, durationMs, initiatedByUser); 254 } 255 }; 256 } 257 } 258 } 259 260 /** 261 * Call to revoke trust on the device. 262 */ 263 public final void revokeTrust() { 264 synchronized (mLock) { 265 if (mPendingGrantTrustTask != null) { 266 mPendingGrantTrustTask = null; 267 } 268 if (mCallback != null) { 269 try { 270 mCallback.revokeTrust(); 271 } catch (RemoteException e) { 272 onError("calling revokeTrust()"); 273 } 274 } 275 } 276 } 277 278 /** 279 * Call to notify the system if the agent is ready to manage trust. 280 * 281 * This property is not persistent across recreating the service and defaults to false. 282 * Therefore this method is typically called when initializing the agent in {@link #onCreate}. 283 * 284 * @param managingTrust indicates if the agent would like to manage trust. 285 */ 286 public final void setManagingTrust(boolean managingTrust) { 287 synchronized (mLock) { 288 if (mManagingTrust != managingTrust) { 289 mManagingTrust = managingTrust; 290 if (mCallback != null) { 291 try { 292 mCallback.setManagingTrust(managingTrust); 293 } catch (RemoteException e) { 294 onError("calling setManagingTrust()"); 295 } 296 } 297 } 298 } 299 } 300 301 @Override 302 public final IBinder onBind(Intent intent) { 303 if (DEBUG) Slog.v(TAG, "onBind() intent = " + intent); 304 return new TrustAgentServiceWrapper(); 305 } 306 307 private final class TrustAgentServiceWrapper extends ITrustAgentService.Stub { 308 @Override /* Binder API */ 309 public void onUnlockAttempt(boolean successful) { 310 mHandler.obtainMessage(MSG_UNLOCK_ATTEMPT, successful ? 1 : 0, 0).sendToTarget(); 311 } 312 313 @Override /* Binder API */ 314 public void onTrustTimeout() { 315 mHandler.sendEmptyMessage(MSG_TRUST_TIMEOUT); 316 } 317 318 @Override /* Binder API */ 319 public void onConfigure(List<PersistableBundle> args, IBinder token) { 320 mHandler.obtainMessage(MSG_CONFIGURE, new ConfigurationData(args, token)) 321 .sendToTarget(); 322 } 323 324 @Override 325 public void onDeviceLocked() throws RemoteException { 326 mHandler.obtainMessage(MSG_DEVICE_LOCKED).sendToTarget(); 327 } 328 329 @Override 330 public void onDeviceUnlocked() throws RemoteException { 331 mHandler.obtainMessage(MSG_DEVICE_UNLOCKED).sendToTarget(); 332 } 333 334 @Override /* Binder API */ 335 public void setCallback(ITrustAgentServiceCallback callback) { 336 synchronized (mLock) { 337 mCallback = callback; 338 // The managingTrust property is false implicitly on the server-side, so we only 339 // need to set it here if the agent has decided to manage trust. 340 if (mManagingTrust) { 341 try { 342 mCallback.setManagingTrust(mManagingTrust); 343 } catch (RemoteException e ) { 344 onError("calling setManagingTrust()"); 345 } 346 } 347 if (mPendingGrantTrustTask != null) { 348 mPendingGrantTrustTask.run(); 349 mPendingGrantTrustTask = null; 350 } 351 } 352 } 353 } 354 355} 356