TrustAgentWrapper.java revision 1221b0628d0b896102c20545b30fa7bafa08ae32
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 com.android.server.trust; 18 19import android.app.AlarmManager; 20import android.app.PendingIntent; 21import android.app.admin.DevicePolicyManager; 22import android.content.BroadcastReceiver; 23import android.content.ComponentName; 24import android.content.Context; 25import android.content.Intent; 26import android.content.IntentFilter; 27import android.content.ServiceConnection; 28import android.net.Uri; 29import android.os.Binder; 30import android.os.Handler; 31import android.os.IBinder; 32import android.os.Message; 33import android.os.PatternMatcher; 34import android.os.PersistableBundle; 35import android.os.RemoteException; 36import android.os.SystemClock; 37import android.os.UserHandle; 38import android.util.Log; 39import android.util.Slog; 40import android.service.trust.ITrustAgentService; 41import android.service.trust.ITrustAgentServiceCallback; 42 43import java.util.Collections; 44import java.util.List; 45 46/** 47 * A wrapper around a TrustAgentService interface. Coordinates communication between 48 * TrustManager and the actual TrustAgent. 49 */ 50public class TrustAgentWrapper { 51 private static final String EXTRA_COMPONENT_NAME = "componentName"; 52 private static final String TRUST_EXPIRED_ACTION = "android.server.trust.TRUST_EXPIRED_ACTION"; 53 private static final String PERMISSION = android.Manifest.permission.PROVIDE_TRUST_AGENT; 54 private static final boolean DEBUG = false; 55 private static final String TAG = "TrustAgentWrapper"; 56 57 private static final int MSG_GRANT_TRUST = 1; 58 private static final int MSG_REVOKE_TRUST = 2; 59 private static final int MSG_TRUST_TIMEOUT = 3; 60 private static final int MSG_RESTART_TIMEOUT = 4; 61 private static final int MSG_SET_TRUST_AGENT_FEATURES_COMPLETED = 5; 62 private static final int MSG_MANAGING_TRUST = 6; 63 64 /** 65 * Time in uptime millis that we wait for the service connection, both when starting 66 * and when the service disconnects. 67 */ 68 private static final long RESTART_TIMEOUT_MILLIS = 5 * 60000; 69 70 /** 71 * Long extra for {@link #MSG_GRANT_TRUST} 72 */ 73 private static final String DATA_DURATION = "duration"; 74 75 private final TrustManagerService mTrustManagerService; 76 private final int mUserId; 77 private final Context mContext; 78 private final ComponentName mName; 79 80 private ITrustAgentService mTrustAgentService; 81 private boolean mBound; 82 private long mScheduledRestartUptimeMillis; 83 private long mMaximumTimeToLock; // from DevicePolicyManager 84 85 // Trust state 86 private boolean mTrusted; 87 private CharSequence mMessage; 88 private boolean mTrustDisabledByDpm; 89 private boolean mManagingTrust; 90 private IBinder mSetTrustAgentFeaturesToken; 91 private AlarmManager mAlarmManager; 92 private final Intent mAlarmIntent; 93 private PendingIntent mAlarmPendingIntent; 94 95 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 96 @Override 97 public void onReceive(Context context, Intent intent) { 98 ComponentName component = intent.getParcelableExtra(EXTRA_COMPONENT_NAME); 99 if (TRUST_EXPIRED_ACTION.equals(intent.getAction()) 100 && mName.equals(component)) { 101 mHandler.removeMessages(MSG_TRUST_TIMEOUT); 102 mHandler.sendEmptyMessage(MSG_TRUST_TIMEOUT); 103 } 104 } 105 }; 106 107 private final Handler mHandler = new Handler() { 108 @Override 109 public void handleMessage(Message msg) { 110 switch (msg.what) { 111 case MSG_GRANT_TRUST: 112 if (!isConnected()) { 113 Log.w(TAG, "Agent is not connected, cannot grant trust: " 114 + mName.flattenToShortString()); 115 return; 116 } 117 mTrusted = true; 118 mMessage = (CharSequence) msg.obj; 119 boolean initiatedByUser = msg.arg1 != 0; 120 long durationMs = msg.getData().getLong(DATA_DURATION); 121 if (durationMs > 0) { 122 final long duration; 123 if (mMaximumTimeToLock != 0) { 124 // Enforce DevicePolicyManager timeout. This is here as a safeguard to 125 // ensure trust agents are evaluating trust state at least as often as 126 // the policy dictates. Admins that want more guarantees should be using 127 // DevicePolicyManager#KEYGUARD_DISABLE_TRUST_AGENTS. 128 duration = Math.min(durationMs, mMaximumTimeToLock); 129 if (DEBUG) { 130 Log.v(TAG, "DPM lock timeout in effect. Timeout adjusted from " 131 + durationMs + " to " + duration); 132 } 133 } else { 134 duration = durationMs; 135 } 136 long expiration = SystemClock.elapsedRealtime() + duration; 137 mAlarmPendingIntent = PendingIntent.getBroadcast(mContext, 0, mAlarmIntent, 138 PendingIntent.FLAG_CANCEL_CURRENT); 139 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, expiration, 140 mAlarmPendingIntent); 141 } 142 mTrustManagerService.mArchive.logGrantTrust(mUserId, mName, 143 (mMessage != null ? mMessage.toString() : null), 144 durationMs, initiatedByUser); 145 mTrustManagerService.updateTrust(mUserId, initiatedByUser); 146 break; 147 case MSG_TRUST_TIMEOUT: 148 if (DEBUG) Slog.v(TAG, "Trust timed out : " + mName.flattenToShortString()); 149 mTrustManagerService.mArchive.logTrustTimeout(mUserId, mName); 150 onTrustTimeout(); 151 // Fall through. 152 case MSG_REVOKE_TRUST: 153 mTrusted = false; 154 mMessage = null; 155 mHandler.removeMessages(MSG_TRUST_TIMEOUT); 156 if (msg.what == MSG_REVOKE_TRUST) { 157 mTrustManagerService.mArchive.logRevokeTrust(mUserId, mName); 158 } 159 mTrustManagerService.updateTrust(mUserId, false); 160 break; 161 case MSG_RESTART_TIMEOUT: 162 destroy(); 163 mTrustManagerService.resetAgent(mName, mUserId); 164 break; 165 case MSG_SET_TRUST_AGENT_FEATURES_COMPLETED: 166 IBinder token = (IBinder) msg.obj; 167 boolean result = msg.arg1 != 0; 168 if (mSetTrustAgentFeaturesToken == token) { 169 mSetTrustAgentFeaturesToken = null; 170 if (mTrustDisabledByDpm && result) { 171 if (DEBUG) Log.v(TAG, "Re-enabling agent because it acknowledged " 172 + "enabled features: " + mName); 173 mTrustDisabledByDpm = false; 174 mTrustManagerService.updateTrust(mUserId, false); 175 } 176 } else { 177 if (DEBUG) Log.w(TAG, "Ignoring MSG_SET_TRUST_AGENT_FEATURES_COMPLETED " 178 + "with obsolete token: " + mName); 179 } 180 break; 181 case MSG_MANAGING_TRUST: 182 mManagingTrust = msg.arg1 != 0; 183 if (!mManagingTrust) { 184 mTrusted = false; 185 mMessage = null; 186 } 187 mTrustManagerService.mArchive.logManagingTrust(mUserId, mName, mManagingTrust); 188 mTrustManagerService.updateTrust(mUserId, false); 189 break; 190 } 191 } 192 }; 193 194 private ITrustAgentServiceCallback mCallback = new ITrustAgentServiceCallback.Stub() { 195 196 @Override 197 public void grantTrust(CharSequence userMessage, long durationMs, boolean initiatedByUser) { 198 if (DEBUG) Slog.v(TAG, "enableTrust(" + userMessage + ", durationMs = " + durationMs 199 + ", initiatedByUser = " + initiatedByUser + ")"); 200 201 Message msg = mHandler.obtainMessage( 202 MSG_GRANT_TRUST, initiatedByUser ? 1 : 0, 0, userMessage); 203 msg.getData().putLong(DATA_DURATION, durationMs); 204 msg.sendToTarget(); 205 } 206 207 @Override 208 public void revokeTrust() { 209 if (DEBUG) Slog.v(TAG, "revokeTrust()"); 210 mHandler.sendEmptyMessage(MSG_REVOKE_TRUST); 211 } 212 213 @Override 214 public void setManagingTrust(boolean managingTrust) { 215 if (DEBUG) Slog.v(TAG, "managingTrust()"); 216 mHandler.obtainMessage(MSG_MANAGING_TRUST, managingTrust ? 1 : 0, 0).sendToTarget(); 217 } 218 219 @Override 220 public void onConfigureCompleted(boolean result, IBinder token) { 221 if (DEBUG) Slog.v(TAG, "onSetTrustAgentFeaturesEnabledCompleted(result=" + result); 222 mHandler.obtainMessage(MSG_SET_TRUST_AGENT_FEATURES_COMPLETED, 223 result ? 1 : 0, 0, token).sendToTarget(); 224 } 225 }; 226 227 private final ServiceConnection mConnection = new ServiceConnection() { 228 @Override 229 public void onServiceConnected(ComponentName name, IBinder service) { 230 if (DEBUG) Log.v(TAG, "TrustAgent started : " + name.flattenToString()); 231 mHandler.removeMessages(MSG_RESTART_TIMEOUT); 232 mTrustAgentService = ITrustAgentService.Stub.asInterface(service); 233 mTrustManagerService.mArchive.logAgentConnected(mUserId, name); 234 setCallback(mCallback); 235 updateDevicePolicyFeatures(); 236 237 if (mTrustManagerService.isDeviceLockedInner(mUserId)) { 238 onDeviceLocked(); 239 } else { 240 onDeviceUnlocked(); 241 } 242 } 243 244 @Override 245 public void onServiceDisconnected(ComponentName name) { 246 if (DEBUG) Log.v(TAG, "TrustAgent disconnected : " + name.flattenToShortString()); 247 mTrustAgentService = null; 248 mManagingTrust = false; 249 mSetTrustAgentFeaturesToken = null; 250 mTrustManagerService.mArchive.logAgentDied(mUserId, name); 251 mHandler.sendEmptyMessage(MSG_REVOKE_TRUST); 252 if (mBound) { 253 scheduleRestart(); 254 } 255 // mTrustDisabledByDpm maintains state 256 } 257 }; 258 259 public TrustAgentWrapper(Context context, TrustManagerService trustManagerService, 260 Intent intent, UserHandle user) { 261 mContext = context; 262 mTrustManagerService = trustManagerService; 263 mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); 264 mUserId = user.getIdentifier(); 265 mName = intent.getComponent(); 266 267 mAlarmIntent = new Intent(TRUST_EXPIRED_ACTION).putExtra(EXTRA_COMPONENT_NAME, mName); 268 mAlarmIntent.setData(Uri.parse(mAlarmIntent.toUri(Intent.URI_INTENT_SCHEME))); 269 mAlarmIntent.setPackage(context.getPackageName()); 270 271 final IntentFilter alarmFilter = new IntentFilter(TRUST_EXPIRED_ACTION); 272 alarmFilter.addDataScheme(mAlarmIntent.getScheme()); 273 final String pathUri = mAlarmIntent.toUri(Intent.URI_INTENT_SCHEME); 274 alarmFilter.addDataPath(pathUri, PatternMatcher.PATTERN_LITERAL); 275 276 // Schedules a restart for when connecting times out. If the connection succeeds, 277 // the restart is canceled in mCallback's onConnected. 278 scheduleRestart(); 279 mBound = context.bindServiceAsUser(intent, mConnection, Context.BIND_AUTO_CREATE, user); 280 if (mBound) { 281 mContext.registerReceiver(mBroadcastReceiver, alarmFilter, PERMISSION, null); 282 } else { 283 Log.e(TAG, "Can't bind to TrustAgent " + mName.flattenToShortString()); 284 } 285 } 286 287 private void onError(Exception e) { 288 Slog.w(TAG , "Remote Exception", e); 289 } 290 291 private void onTrustTimeout() { 292 try { 293 if (mTrustAgentService != null) mTrustAgentService.onTrustTimeout(); 294 } catch (RemoteException e) { 295 onError(e); 296 } 297 } 298 299 /** 300 * @see android.service.trust.TrustAgentService#onUnlockAttempt(boolean) 301 */ 302 public void onUnlockAttempt(boolean successful) { 303 try { 304 if (mTrustAgentService != null) mTrustAgentService.onUnlockAttempt(successful); 305 } catch (RemoteException e) { 306 onError(e); 307 } 308 } 309 310 /** 311 * @see android.service.trust.TrustAgentService#onDeviceLocked() 312 */ 313 public void onDeviceLocked() { 314 try { 315 if (mTrustAgentService != null) mTrustAgentService.onDeviceLocked(); 316 } catch (RemoteException e) { 317 onError(e); 318 } 319 } 320 321 /** 322 * @see android.service.trust.TrustAgentService#onDeviceUnlocked() 323 */ 324 public void onDeviceUnlocked() { 325 try { 326 if (mTrustAgentService != null) mTrustAgentService.onDeviceUnlocked(); 327 } catch (RemoteException e) { 328 onError(e); 329 } 330 } 331 332 private void setCallback(ITrustAgentServiceCallback callback) { 333 try { 334 if (mTrustAgentService != null) { 335 mTrustAgentService.setCallback(callback); 336 } 337 } catch (RemoteException e) { 338 onError(e); 339 } 340 } 341 342 boolean updateDevicePolicyFeatures() { 343 boolean trustDisabled = false; 344 if (DEBUG) Slog.v(TAG, "updateDevicePolicyFeatures(" + mName + ")"); 345 try { 346 if (mTrustAgentService != null) { 347 DevicePolicyManager dpm = 348 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); 349 350 if ((dpm.getKeyguardDisabledFeatures(null, mUserId) 351 & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0) { 352 List<PersistableBundle> config = dpm.getTrustAgentConfiguration( 353 null, mName, mUserId); 354 trustDisabled = true; 355 if (DEBUG) Slog.v(TAG, "Detected trust agents disabled. Config = " + config); 356 if (config != null && config.size() > 0) { 357 if (DEBUG) { 358 Slog.v(TAG, "TrustAgent " + mName.flattenToShortString() 359 + " disabled until it acknowledges "+ config); 360 } 361 mSetTrustAgentFeaturesToken = new Binder(); 362 mTrustAgentService.onConfigure(config, mSetTrustAgentFeaturesToken); 363 } 364 } else { 365 mTrustAgentService.onConfigure(Collections.EMPTY_LIST, null); 366 } 367 final long maxTimeToLock = dpm.getMaximumTimeToLock(null); 368 if (maxTimeToLock != mMaximumTimeToLock) { 369 // If the timeout changes, cancel the alarm and send a timeout event to have 370 // the agent re-evaluate trust. 371 mMaximumTimeToLock = maxTimeToLock; 372 if (mAlarmPendingIntent != null) { 373 mAlarmManager.cancel(mAlarmPendingIntent); 374 mAlarmPendingIntent = null; 375 mHandler.sendEmptyMessage(MSG_TRUST_TIMEOUT); 376 } 377 } 378 } 379 } catch (RemoteException e) { 380 onError(e); 381 } 382 if (mTrustDisabledByDpm != trustDisabled) { 383 mTrustDisabledByDpm = trustDisabled; 384 mTrustManagerService.updateTrust(mUserId, false); 385 } 386 return trustDisabled; 387 } 388 389 public boolean isTrusted() { 390 return mTrusted && mManagingTrust && !mTrustDisabledByDpm; 391 } 392 393 public boolean isManagingTrust() { 394 return mManagingTrust && !mTrustDisabledByDpm; 395 } 396 397 public CharSequence getMessage() { 398 return mMessage; 399 } 400 401 public void destroy() { 402 mHandler.removeMessages(MSG_RESTART_TIMEOUT); 403 404 if (!mBound) { 405 return; 406 } 407 if (DEBUG) Log.v(TAG, "TrustAgent unbound : " + mName.flattenToShortString()); 408 mTrustManagerService.mArchive.logAgentStopped(mUserId, mName); 409 mContext.unbindService(mConnection); 410 mBound = false; 411 mContext.unregisterReceiver(mBroadcastReceiver); 412 mTrustAgentService = null; 413 mSetTrustAgentFeaturesToken = null; 414 mHandler.sendEmptyMessage(MSG_REVOKE_TRUST); 415 } 416 417 public boolean isConnected() { 418 return mTrustAgentService != null; 419 } 420 421 public boolean isBound() { 422 return mBound; 423 } 424 425 /** 426 * If not connected, returns the time at which the agent is restarted. 427 * 428 * @return restart time in uptime millis. 429 */ 430 public long getScheduledRestartUptimeMillis() { 431 return mScheduledRestartUptimeMillis; 432 } 433 434 private void scheduleRestart() { 435 mHandler.removeMessages(MSG_RESTART_TIMEOUT); 436 mScheduledRestartUptimeMillis = SystemClock.uptimeMillis() + RESTART_TIMEOUT_MILLIS; 437 mHandler.sendEmptyMessageAtTime(MSG_RESTART_TIMEOUT, mScheduledRestartUptimeMillis); 438 } 439} 440