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