TrustAgentService.java revision 8f21158fe64eb93ff005dc1b831b282b95531023
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.Message; 32import android.os.RemoteException; 33import android.util.Log; 34import android.util.Slog; 35 36/** 37 * A service that notifies the system about whether it believes the environment of the device 38 * to be trusted. 39 * 40 * <p>Trust agents may only be provided by the platform.</p> 41 * 42 * <p>To extend this class, you must declare the service in your manifest file with 43 * the {@link android.Manifest.permission#BIND_TRUST_AGENT} permission 44 * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p> 45 * <pre> 46 * <service android:name=".TrustAgent" 47 * android:label="@string/service_name" 48 * android:permission="android.permission.BIND_TRUST_AGENT"> 49 * <intent-filter> 50 * <action android:name="android.service.trust.TrustAgentService" /> 51 * </intent-filter> 52 * <meta-data android:name="android.service.trust.trustagent" 53 * android:value="@xml/trust_agent" /> 54 * </service></pre> 55 * 56 * <p>The associated meta-data file can specify an activity that is accessible through Settings 57 * and should allow configuring the trust agent, as defined in 58 * {@link android.R.styleable#TrustAgent}. For example:</p> 59 * 60 * <pre> 61 * <trust-agent xmlns:android="http://schemas.android.com/apk/res/android" 62 * android:settingsActivity=".TrustAgentSettings" /></pre> 63 * 64 * @hide 65 */ 66@SystemApi 67public class TrustAgentService extends Service { 68 private final String TAG = TrustAgentService.class.getSimpleName() + 69 "[" + getClass().getSimpleName() + "]"; 70 private static final boolean DEBUG = false; 71 72 // Temporary workaround to allow current trust agent implementations to continue working. 73 // This and the code guarded by this should be removed before shipping. 74 // If true, calls setManagingTrust(true) after onCreate, if it wasn't already set. 75 // TODO: Remove this once all agents are updated. 76 private static final boolean SET_MANAGED_FOR_LEGACY_AGENTS = true; 77 78 /** 79 * The {@link Intent} that must be declared as handled by the service. 80 */ 81 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) 82 public static final String SERVICE_INTERFACE 83 = "android.service.trust.TrustAgentService"; 84 85 /** 86 * The name of the {@code meta-data} tag pointing to additional configuration of the trust 87 * agent. 88 */ 89 public static final String TRUST_AGENT_META_DATA = "android.service.trust.trustagent"; 90 91 /** 92 * A white list of features that the given trust agent should support when otherwise disabled 93 * by device policy. 94 */ 95 public static final String KEY_FEATURES = "trust_agent_features"; 96 97 private static final int MSG_UNLOCK_ATTEMPT = 1; 98 private static final int MSG_SET_TRUST_AGENT_FEATURES_ENABLED = 2; 99 100 private ITrustAgentServiceCallback mCallback; 101 102 private Runnable mPendingGrantTrustTask; 103 104 private boolean mManagingTrust; 105 106 // Lock used to access mPendingGrantTrustTask and mCallback. 107 private final Object mLock = new Object(); 108 109 private Handler mHandler = new Handler() { 110 public void handleMessage(android.os.Message msg) { 111 switch (msg.what) { 112 case MSG_UNLOCK_ATTEMPT: 113 onUnlockAttempt(msg.arg1 != 0); 114 break; 115 case MSG_SET_TRUST_AGENT_FEATURES_ENABLED: 116 Bundle features = msg.peekData(); 117 IBinder token = (IBinder) msg.obj; 118 boolean result = onSetTrustAgentFeaturesEnabled(features); 119 try { 120 synchronized (mLock) { 121 mCallback.onSetTrustAgentFeaturesEnabledCompleted(result, token); 122 } 123 } catch (RemoteException e) { 124 onError("calling onSetTrustAgentFeaturesEnabledCompleted()"); 125 } 126 break; 127 } 128 } 129 }; 130 131 @Override 132 public void onCreate() { 133 // TODO: Remove this once all agents are updated. 134 if (SET_MANAGED_FOR_LEGACY_AGENTS) { 135 setManagingTrust(true); 136 } 137 138 super.onCreate(); 139 ComponentName component = new ComponentName(this, getClass()); 140 try { 141 ServiceInfo serviceInfo = getPackageManager().getServiceInfo(component, 0 /* flags */); 142 if (!Manifest.permission.BIND_TRUST_AGENT.equals(serviceInfo.permission)) { 143 throw new IllegalStateException(component.flattenToShortString() 144 + " is not declared with the permission " 145 + "\"" + Manifest.permission.BIND_TRUST_AGENT + "\""); 146 } 147 } catch (PackageManager.NameNotFoundException e) { 148 Log.e(TAG, "Can't get ServiceInfo for " + component.toShortString()); 149 } 150 } 151 152 /** 153 * Called when the user attempted to authenticate on the device. 154 * 155 * @param successful true if the attempt succeeded 156 */ 157 public void onUnlockAttempt(boolean successful) { 158 } 159 160 private void onError(String msg) { 161 Slog.v(TAG, "Remote exception while " + msg); 162 } 163 164 /** 165 * Called when device policy wants to restrict features in the TrustAgent in response to 166 * {@link DevicePolicyManager#setTrustAgentFeaturesEnabled(ComponentName, ComponentName, java.util.List) }. 167 * TrustAgents that support this feature should overload this method and return 'true'. 168 * 169 * The list of options can be obtained by calling 170 * options.getStringArrayList({@link #KEY_FEATURES}). Presence of a feature string in the list 171 * means it should be enabled ("white-listed"). Absence of the feature means it should be 172 * disabled. An empty list means all features should be disabled. 173 * 174 * This function is only called if {@link DevicePolicyManager#KEYGUARD_DISABLE_TRUST_AGENTS} is 175 * set. 176 * 177 * @param options Option feature bundle. 178 * @return true if the {@link #TrustAgentService()} supports this feature. 179 */ 180 public boolean onSetTrustAgentFeaturesEnabled(Bundle options) { 181 return false; 182 } 183 184 /** 185 * Call to grant trust on the device. 186 * 187 * @param message describes why the device is trusted, e.g. "Trusted by location". 188 * @param durationMs amount of time in milliseconds to keep the device in a trusted state. Trust 189 * for this agent will automatically be revoked when the timeout expires. 190 * @param initiatedByUser indicates that the user has explicitly initiated an action that proves 191 * the user is about to use the device. 192 * @throws IllegalStateException if the agent is not currently managing trust. 193 */ 194 public final void grantTrust( 195 final CharSequence message, final long durationMs, final boolean initiatedByUser) { 196 synchronized (mLock) { 197 if (!mManagingTrust) { 198 throw new IllegalStateException("Cannot grant trust if agent is not managing trust." 199 + " Call setManagingTrust(true) first."); 200 } 201 if (mCallback != null) { 202 try { 203 mCallback.grantTrust(message.toString(), durationMs, initiatedByUser); 204 } catch (RemoteException e) { 205 onError("calling enableTrust()"); 206 } 207 } else { 208 // Remember trust has been granted so we can effectively grant it once the service 209 // is bound. 210 mPendingGrantTrustTask = new Runnable() { 211 @Override 212 public void run() { 213 grantTrust(message, durationMs, initiatedByUser); 214 } 215 }; 216 } 217 } 218 } 219 220 /** 221 * Call to revoke trust on the device. 222 */ 223 public final void revokeTrust() { 224 synchronized (mLock) { 225 if (mPendingGrantTrustTask != null) { 226 mPendingGrantTrustTask = null; 227 } 228 if (mCallback != null) { 229 try { 230 mCallback.revokeTrust(); 231 } catch (RemoteException e) { 232 onError("calling revokeTrust()"); 233 } 234 } 235 } 236 } 237 238 /** 239 * Call to notify the system if the agent is ready to manage trust. 240 * 241 * This property is not persistent across recreating the service and defaults to false. 242 * Therefore this method is typically called when initializing the agent in {@link #onCreate}. 243 * 244 * @param managingTrust indicates if the agent would like to manage trust. 245 */ 246 public final void setManagingTrust(boolean managingTrust) { 247 synchronized (mLock) { 248 if (mManagingTrust != managingTrust) { 249 mManagingTrust = managingTrust; 250 if (mCallback != null) { 251 try { 252 mCallback.setManagingTrust(managingTrust); 253 } catch (RemoteException e) { 254 onError("calling setManagingTrust()"); 255 } 256 } 257 } 258 } 259 } 260 261 @Override 262 public final IBinder onBind(Intent intent) { 263 if (DEBUG) Slog.v(TAG, "onBind() intent = " + intent); 264 return new TrustAgentServiceWrapper(); 265 } 266 267 private final class TrustAgentServiceWrapper extends ITrustAgentService.Stub { 268 @Override 269 public void onUnlockAttempt(boolean successful) { 270 mHandler.obtainMessage(MSG_UNLOCK_ATTEMPT, successful ? 1 : 0, 0) 271 .sendToTarget(); 272 } 273 274 @Override 275 public void setCallback(ITrustAgentServiceCallback callback) { 276 synchronized (mLock) { 277 mCallback = callback; 278 // The managingTrust property is false implicitly on the server-side, so we only 279 // need to set it here if the agent has decided to manage trust. 280 if (mManagingTrust) { 281 try { 282 mCallback.setManagingTrust(mManagingTrust); 283 } catch (RemoteException e ) { 284 onError("calling setManagingTrust()"); 285 } 286 } 287 if (mPendingGrantTrustTask != null) { 288 mPendingGrantTrustTask.run(); 289 mPendingGrantTrustTask = null; 290 } 291 } 292 } 293 294 @Override 295 public void setTrustAgentFeaturesEnabled(Bundle features, IBinder token) { 296 Message msg = mHandler.obtainMessage(MSG_SET_TRUST_AGENT_FEATURES_ENABLED, token); 297 msg.setData(features); 298 msg.sendToTarget(); 299 } 300 } 301 302} 303