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