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 17 package com.android.server.trust; 18 19 import android.annotation.TargetApi; 20 import android.app.AlarmManager; 21 import android.app.PendingIntent; 22 import android.app.admin.DevicePolicyManager; 23 import android.content.BroadcastReceiver; 24 import android.content.ComponentName; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.IntentFilter; 28 import android.content.ServiceConnection; 29 import android.net.Uri; 30 import android.os.Binder; 31 import android.os.Build; 32 import android.os.Handler; 33 import android.os.IBinder; 34 import android.os.Message; 35 import android.os.PatternMatcher; 36 import android.os.PersistableBundle; 37 import android.os.RemoteException; 38 import android.os.SystemClock; 39 import android.os.UserHandle; 40 import android.service.trust.ITrustAgentService; 41 import android.service.trust.ITrustAgentServiceCallback; 42 import android.service.trust.TrustAgentService; 43 import android.util.Log; 44 import android.util.Slog; 45 46 import java.util.Collections; 47 import java.util.List; 48 49 /** 50 * A wrapper around a TrustAgentService interface. Coordinates communication between 51 * TrustManager and the actual TrustAgent. 52 */ 53 @TargetApi(Build.VERSION_CODES.LOLLIPOP) 54 public class TrustAgentWrapper { 55 private static final String EXTRA_COMPONENT_NAME = "componentName"; 56 private static final String TRUST_EXPIRED_ACTION = "android.server.trust.TRUST_EXPIRED_ACTION"; 57 private static final String PERMISSION = android.Manifest.permission.PROVIDE_TRUST_AGENT; 58 private static final boolean DEBUG = TrustManagerService.DEBUG; 59 private static final String TAG = "TrustAgentWrapper"; 60 61 private static final int MSG_GRANT_TRUST = 1; 62 private static final int MSG_REVOKE_TRUST = 2; 63 private static final int MSG_TRUST_TIMEOUT = 3; 64 private static final int MSG_RESTART_TIMEOUT = 4; 65 private static final int MSG_SET_TRUST_AGENT_FEATURES_COMPLETED = 5; 66 private static final int MSG_MANAGING_TRUST = 6; 67 private static final int MSG_ADD_ESCROW_TOKEN = 7; 68 private static final int MSG_REMOVE_ESCROW_TOKEN = 8; 69 private static final int MSG_ESCROW_TOKEN_STATE = 9; 70 private static final int MSG_UNLOCK_USER = 10; 71 private static final int MSG_SHOW_KEYGUARD_ERROR_MESSAGE = 11; 72 73 /** 74 * Time in uptime millis that we wait for the service connection, both when starting 75 * and when the service disconnects. 76 */ 77 private static final long RESTART_TIMEOUT_MILLIS = 5 * 60000; 78 79 /** 80 * Long extra for {@link #MSG_GRANT_TRUST} 81 */ 82 private static final String DATA_DURATION = "duration"; 83 private static final String DATA_ESCROW_TOKEN = "escrow_token"; 84 private static final String DATA_HANDLE = "handle"; 85 private static final String DATA_USER_ID = "user_id"; 86 private static final String DATA_MESSAGE = "message"; 87 88 private final TrustManagerService mTrustManagerService; 89 private final int mUserId; 90 private final Context mContext; 91 private final ComponentName mName; 92 93 private ITrustAgentService mTrustAgentService; 94 private boolean mBound; 95 private long mScheduledRestartUptimeMillis; 96 private long mMaximumTimeToLock; // from DevicePolicyManager 97 private boolean mPendingSuccessfulUnlock = false; 98 99 // Trust state 100 private boolean mTrusted; 101 private CharSequence mMessage; 102 private boolean mTrustDisabledByDpm; 103 private boolean mManagingTrust; 104 private IBinder mSetTrustAgentFeaturesToken; 105 private AlarmManager mAlarmManager; 106 private final Intent mAlarmIntent; 107 private PendingIntent mAlarmPendingIntent; 108 109 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 110 @Override 111 public void onReceive(Context context, Intent intent) { 112 ComponentName component = intent.getParcelableExtra(EXTRA_COMPONENT_NAME); 113 if (TRUST_EXPIRED_ACTION.equals(intent.getAction()) 114 && mName.equals(component)) { 115 mHandler.removeMessages(MSG_TRUST_TIMEOUT); 116 mHandler.sendEmptyMessage(MSG_TRUST_TIMEOUT); 117 } 118 } 119 }; 120 121 private final Handler mHandler = new Handler() { 122 @Override 123 public void handleMessage(Message msg) { 124 switch (msg.what) { 125 case MSG_GRANT_TRUST: 126 if (!isConnected()) { 127 Log.w(TAG, "Agent is not connected, cannot grant trust: " 128 + mName.flattenToShortString()); 129 return; 130 } 131 mTrusted = true; 132 mMessage = (CharSequence) msg.obj; 133 int flags = msg.arg1; 134 long durationMs = msg.getData().getLong(DATA_DURATION); 135 if (durationMs > 0) { 136 final long duration; 137 if (mMaximumTimeToLock != 0) { 138 // Enforce DevicePolicyManager timeout. This is here as a safeguard to 139 // ensure trust agents are evaluating trust state at least as often as 140 // the policy dictates. Admins that want more guarantees should be using 141 // DevicePolicyManager#KEYGUARD_DISABLE_TRUST_AGENTS. 142 duration = Math.min(durationMs, mMaximumTimeToLock); 143 if (DEBUG) { 144 Slog.d(TAG, "DPM lock timeout in effect. Timeout adjusted from " 145 + durationMs + " to " + duration); 146 } 147 } else { 148 duration = durationMs; 149 } 150 long expiration = SystemClock.elapsedRealtime() + duration; 151 mAlarmPendingIntent = PendingIntent.getBroadcast(mContext, 0, mAlarmIntent, 152 PendingIntent.FLAG_CANCEL_CURRENT); 153 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, expiration, 154 mAlarmPendingIntent); 155 } 156 mTrustManagerService.mArchive.logGrantTrust(mUserId, mName, 157 (mMessage != null ? mMessage.toString() : null), 158 durationMs, flags); 159 mTrustManagerService.updateTrust(mUserId, flags); 160 break; 161 case MSG_TRUST_TIMEOUT: 162 if (DEBUG) Slog.d(TAG, "Trust timed out : " + mName.flattenToShortString()); 163 mTrustManagerService.mArchive.logTrustTimeout(mUserId, mName); 164 onTrustTimeout(); 165 // Fall through. 166 case MSG_REVOKE_TRUST: 167 mTrusted = false; 168 mMessage = null; 169 mHandler.removeMessages(MSG_TRUST_TIMEOUT); 170 if (msg.what == MSG_REVOKE_TRUST) { 171 mTrustManagerService.mArchive.logRevokeTrust(mUserId, mName); 172 } 173 mTrustManagerService.updateTrust(mUserId, 0); 174 break; 175 case MSG_RESTART_TIMEOUT: 176 Slog.w(TAG, "Connection attempt to agent " + mName.flattenToShortString() 177 + " timed out, rebinding"); 178 destroy(); 179 mTrustManagerService.resetAgent(mName, mUserId); 180 break; 181 case MSG_SET_TRUST_AGENT_FEATURES_COMPLETED: 182 IBinder token = (IBinder) msg.obj; 183 boolean result = msg.arg1 != 0; 184 if (mSetTrustAgentFeaturesToken == token) { 185 mSetTrustAgentFeaturesToken = null; 186 if (mTrustDisabledByDpm && result) { 187 if (DEBUG) Slog.d(TAG, "Re-enabling agent because it acknowledged " 188 + "enabled features: " + mName.flattenToShortString()); 189 mTrustDisabledByDpm = false; 190 mTrustManagerService.updateTrust(mUserId, 0); 191 } 192 } else { 193 if (DEBUG) Slog.w(TAG, "Ignoring MSG_SET_TRUST_AGENT_FEATURES_COMPLETED " 194 + "with obsolete token: " + mName.flattenToShortString()); 195 } 196 break; 197 case MSG_MANAGING_TRUST: 198 mManagingTrust = msg.arg1 != 0; 199 if (!mManagingTrust) { 200 mTrusted = false; 201 mMessage = null; 202 } 203 mTrustManagerService.mArchive.logManagingTrust(mUserId, mName, mManagingTrust); 204 mTrustManagerService.updateTrust(mUserId, 0); 205 break; 206 case MSG_ADD_ESCROW_TOKEN: { 207 byte[] eToken = msg.getData().getByteArray(DATA_ESCROW_TOKEN); 208 int userId = msg.getData().getInt(DATA_USER_ID); 209 long handle = mTrustManagerService.addEscrowToken(eToken, userId); 210 boolean resultDeliverred = false; 211 try { 212 if (mTrustAgentService != null) { 213 mTrustAgentService.onEscrowTokenAdded( 214 eToken, handle, UserHandle.of(userId)); 215 resultDeliverred = true; 216 } 217 } catch (RemoteException e) { 218 onError(e); 219 } 220 221 if (!resultDeliverred) { 222 mTrustManagerService.removeEscrowToken(handle, userId); 223 } 224 break; 225 } 226 case MSG_ESCROW_TOKEN_STATE: { 227 long handle = msg.getData().getLong(DATA_HANDLE); 228 int userId = msg.getData().getInt(DATA_USER_ID); 229 boolean active = mTrustManagerService.isEscrowTokenActive(handle, userId); 230 try { 231 if (mTrustAgentService != null) { 232 mTrustAgentService.onTokenStateReceived(handle, 233 active ? TrustAgentService.TOKEN_STATE_ACTIVE 234 : TrustAgentService.TOKEN_STATE_INACTIVE); 235 } 236 } catch (RemoteException e) { 237 onError(e); 238 } 239 break; 240 } 241 case MSG_REMOVE_ESCROW_TOKEN: { 242 long handle = msg.getData().getLong(DATA_HANDLE); 243 int userId = msg.getData().getInt(DATA_USER_ID); 244 boolean success = mTrustManagerService.removeEscrowToken(handle, userId); 245 try { 246 if (mTrustAgentService != null) { 247 mTrustAgentService.onEscrowTokenRemoved(handle, success); 248 } 249 } catch (RemoteException e) { 250 onError(e); 251 } 252 break; 253 } 254 case MSG_UNLOCK_USER: { 255 long handle = msg.getData().getLong(DATA_HANDLE); 256 int userId = msg.getData().getInt(DATA_USER_ID); 257 byte[] eToken = msg.getData().getByteArray(DATA_ESCROW_TOKEN); 258 mTrustManagerService.unlockUserWithToken(handle, eToken, userId); 259 break; 260 } 261 case MSG_SHOW_KEYGUARD_ERROR_MESSAGE: { 262 CharSequence message = msg.getData().getCharSequence(DATA_MESSAGE); 263 mTrustManagerService.showKeyguardErrorMessage(message); 264 break; 265 } 266 } 267 } 268 }; 269 270 private ITrustAgentServiceCallback mCallback = new ITrustAgentServiceCallback.Stub() { 271 272 @Override 273 public void grantTrust(CharSequence userMessage, long durationMs, int flags) { 274 if (DEBUG) Slog.d(TAG, "enableTrust(" + userMessage + ", durationMs = " + durationMs 275 + ", flags = " + flags + ")"); 276 277 Message msg = mHandler.obtainMessage( 278 MSG_GRANT_TRUST, flags, 0, userMessage); 279 msg.getData().putLong(DATA_DURATION, durationMs); 280 msg.sendToTarget(); 281 } 282 283 @Override 284 public void revokeTrust() { 285 if (DEBUG) Slog.d(TAG, "revokeTrust()"); 286 mHandler.sendEmptyMessage(MSG_REVOKE_TRUST); 287 } 288 289 @Override 290 public void setManagingTrust(boolean managingTrust) { 291 if (DEBUG) Slog.d(TAG, "managingTrust()"); 292 mHandler.obtainMessage(MSG_MANAGING_TRUST, managingTrust ? 1 : 0, 0).sendToTarget(); 293 } 294 295 @Override 296 public void onConfigureCompleted(boolean result, IBinder token) { 297 if (DEBUG) Slog.d(TAG, "onSetTrustAgentFeaturesEnabledCompleted(result=" + result); 298 mHandler.obtainMessage(MSG_SET_TRUST_AGENT_FEATURES_COMPLETED, 299 result ? 1 : 0, 0, token).sendToTarget(); 300 } 301 302 @Override 303 public void addEscrowToken(byte[] token, int userId) { 304 if (mContext.getResources() 305 .getBoolean(com.android.internal.R.bool.config_allowEscrowTokenForTrustAgent)) { 306 throw new SecurityException("Escrow token API is not allowed."); 307 } 308 309 if (DEBUG) Slog.d(TAG, "adding escrow token for user " + userId); 310 Message msg = mHandler.obtainMessage(MSG_ADD_ESCROW_TOKEN); 311 msg.getData().putByteArray(DATA_ESCROW_TOKEN, token); 312 msg.getData().putInt(DATA_USER_ID, userId); 313 msg.sendToTarget(); 314 } 315 316 @Override 317 public void isEscrowTokenActive(long handle, int userId) { 318 if (mContext.getResources() 319 .getBoolean(com.android.internal.R.bool.config_allowEscrowTokenForTrustAgent)) { 320 throw new SecurityException("Escrow token API is not allowed."); 321 } 322 323 if (DEBUG) Slog.d(TAG, "checking the state of escrow token on user " + userId); 324 Message msg = mHandler.obtainMessage(MSG_ESCROW_TOKEN_STATE); 325 msg.getData().putLong(DATA_HANDLE, handle); 326 msg.getData().putInt(DATA_USER_ID, userId); 327 msg.sendToTarget(); 328 } 329 330 @Override 331 public void removeEscrowToken(long handle, int userId) { 332 if (mContext.getResources() 333 .getBoolean(com.android.internal.R.bool.config_allowEscrowTokenForTrustAgent)) { 334 throw new SecurityException("Escrow token API is not allowed."); 335 } 336 337 if (DEBUG) Slog.d(TAG, "removing escrow token on user " + userId); 338 Message msg = mHandler.obtainMessage(MSG_REMOVE_ESCROW_TOKEN); 339 msg.getData().putLong(DATA_HANDLE, handle); 340 msg.getData().putInt(DATA_USER_ID, userId); 341 msg.sendToTarget(); 342 } 343 344 @Override 345 public void unlockUserWithToken(long handle, byte[] token, int userId) { 346 if (mContext.getResources() 347 .getBoolean(com.android.internal.R.bool.config_allowEscrowTokenForTrustAgent)) { 348 throw new SecurityException("Escrow token API is not allowed."); 349 } 350 351 if (DEBUG) Slog.d(TAG, "unlocking user " + userId); 352 Message msg = mHandler.obtainMessage(MSG_UNLOCK_USER); 353 msg.getData().putInt(DATA_USER_ID, userId); 354 msg.getData().putLong(DATA_HANDLE, handle); 355 msg.getData().putByteArray(DATA_ESCROW_TOKEN, token); 356 msg.sendToTarget(); 357 } 358 359 @Override 360 public void showKeyguardErrorMessage(CharSequence message) { 361 if (DEBUG) Slog.d(TAG, "Showing keyguard error message: " + message); 362 Message msg = mHandler.obtainMessage(MSG_SHOW_KEYGUARD_ERROR_MESSAGE); 363 msg.getData().putCharSequence(DATA_MESSAGE, message); 364 msg.sendToTarget(); 365 } 366 }; 367 368 private final ServiceConnection mConnection = new ServiceConnection() { 369 @Override 370 public void onServiceConnected(ComponentName name, IBinder service) { 371 if (DEBUG) Slog.d(TAG, "TrustAgent started : " + name.flattenToString()); 372 mHandler.removeMessages(MSG_RESTART_TIMEOUT); 373 mTrustAgentService = ITrustAgentService.Stub.asInterface(service); 374 mTrustManagerService.mArchive.logAgentConnected(mUserId, name); 375 setCallback(mCallback); 376 updateDevicePolicyFeatures(); 377 378 if (mPendingSuccessfulUnlock) { 379 onUnlockAttempt(true); 380 mPendingSuccessfulUnlock = false; 381 } 382 383 if (mTrustManagerService.isDeviceLockedInner(mUserId)) { 384 onDeviceLocked(); 385 } else { 386 onDeviceUnlocked(); 387 } 388 } 389 390 @Override 391 public void onServiceDisconnected(ComponentName name) { 392 if (DEBUG) Slog.d(TAG, "TrustAgent disconnected : " + name.flattenToShortString()); 393 mTrustAgentService = null; 394 mManagingTrust = false; 395 mSetTrustAgentFeaturesToken = null; 396 mTrustManagerService.mArchive.logAgentDied(mUserId, name); 397 mHandler.sendEmptyMessage(MSG_REVOKE_TRUST); 398 if (mBound) { 399 scheduleRestart(); 400 } 401 // mTrustDisabledByDpm maintains state 402 } 403 }; 404 TrustAgentWrapper(Context context, TrustManagerService trustManagerService, Intent intent, UserHandle user)405 public TrustAgentWrapper(Context context, TrustManagerService trustManagerService, 406 Intent intent, UserHandle user) { 407 mContext = context; 408 mTrustManagerService = trustManagerService; 409 mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); 410 mUserId = user.getIdentifier(); 411 mName = intent.getComponent(); 412 413 mAlarmIntent = new Intent(TRUST_EXPIRED_ACTION).putExtra(EXTRA_COMPONENT_NAME, mName); 414 mAlarmIntent.setData(Uri.parse(mAlarmIntent.toUri(Intent.URI_INTENT_SCHEME))); 415 mAlarmIntent.setPackage(context.getPackageName()); 416 417 final IntentFilter alarmFilter = new IntentFilter(TRUST_EXPIRED_ACTION); 418 alarmFilter.addDataScheme(mAlarmIntent.getScheme()); 419 final String pathUri = mAlarmIntent.toUri(Intent.URI_INTENT_SCHEME); 420 alarmFilter.addDataPath(pathUri, PatternMatcher.PATTERN_LITERAL); 421 422 // Schedules a restart for when connecting times out. If the connection succeeds, 423 // the restart is canceled in mCallback's onConnected. 424 scheduleRestart(); 425 mBound = context.bindServiceAsUser(intent, mConnection, 426 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, user); 427 if (mBound) { 428 mContext.registerReceiver(mBroadcastReceiver, alarmFilter, PERMISSION, null); 429 } else { 430 Log.e(TAG, "Can't bind to TrustAgent " + mName.flattenToShortString()); 431 } 432 } 433 onError(Exception e)434 private void onError(Exception e) { 435 Slog.w(TAG , "Exception ", e); 436 } 437 onTrustTimeout()438 private void onTrustTimeout() { 439 try { 440 if (mTrustAgentService != null) mTrustAgentService.onTrustTimeout(); 441 } catch (RemoteException e) { 442 onError(e); 443 } 444 } 445 446 /** 447 * @see android.service.trust.TrustAgentService#onUnlockAttempt(boolean) 448 */ onUnlockAttempt(boolean successful)449 public void onUnlockAttempt(boolean successful) { 450 try { 451 if (mTrustAgentService != null) { 452 mTrustAgentService.onUnlockAttempt(successful); 453 } else { 454 mPendingSuccessfulUnlock = successful; 455 } 456 } catch (RemoteException e) { 457 onError(e); 458 } 459 } 460 461 /** 462 * @see android.service.trust.TrustAgentService#onUnlockLockout(int) 463 */ onUnlockLockout(int timeoutMs)464 public void onUnlockLockout(int timeoutMs) { 465 try { 466 if (mTrustAgentService != null) { 467 mTrustAgentService.onUnlockLockout(timeoutMs); 468 } 469 } catch (RemoteException e) { 470 onError(e); 471 } 472 } 473 474 /** 475 * @see android.service.trust.TrustAgentService#onDeviceLocked() 476 */ onDeviceLocked()477 public void onDeviceLocked() { 478 try { 479 if (mTrustAgentService != null) mTrustAgentService.onDeviceLocked(); 480 } catch (RemoteException e) { 481 onError(e); 482 } 483 } 484 485 /** 486 * @see android.service.trust.TrustAgentService#onDeviceUnlocked() 487 */ onDeviceUnlocked()488 public void onDeviceUnlocked() { 489 try { 490 if (mTrustAgentService != null) mTrustAgentService.onDeviceUnlocked(); 491 } catch (RemoteException e) { 492 onError(e); 493 } 494 } 495 496 /** 497 * @see android.service.trust.TrustAgentService#onTokenStateReceived() 498 * 499 */ onEscrowTokenActivated(long handle, int userId)500 public void onEscrowTokenActivated(long handle, int userId) { 501 if (DEBUG) Slog.d(TAG, "onEscrowTokenActivated: " + handle + " user: " + userId); 502 if (mTrustAgentService != null) { 503 try { 504 mTrustAgentService.onTokenStateReceived(handle, 505 TrustAgentService.TOKEN_STATE_ACTIVE); 506 } catch (RemoteException e) { 507 onError(e); 508 } 509 } 510 } setCallback(ITrustAgentServiceCallback callback)511 private void setCallback(ITrustAgentServiceCallback callback) { 512 try { 513 if (mTrustAgentService != null) { 514 mTrustAgentService.setCallback(callback); 515 } 516 } catch (RemoteException e) { 517 onError(e); 518 } 519 } 520 updateDevicePolicyFeatures()521 boolean updateDevicePolicyFeatures() { 522 boolean trustDisabled = false; 523 if (DEBUG) Slog.d(TAG, "updateDevicePolicyFeatures(" + mName + ")"); 524 try { 525 if (mTrustAgentService != null) { 526 DevicePolicyManager dpm = 527 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); 528 529 if ((dpm.getKeyguardDisabledFeatures(null, mUserId) 530 & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0) { 531 List<PersistableBundle> config = dpm.getTrustAgentConfiguration( 532 null, mName, mUserId); 533 trustDisabled = true; 534 if (DEBUG) Slog.d(TAG, "Detected trust agents disabled. Config = " + config); 535 if (config != null && config.size() > 0) { 536 if (DEBUG) { 537 Slog.d(TAG, "TrustAgent " + mName.flattenToShortString() 538 + " disabled until it acknowledges "+ config); 539 } 540 mSetTrustAgentFeaturesToken = new Binder(); 541 mTrustAgentService.onConfigure(config, mSetTrustAgentFeaturesToken); 542 } 543 } else { 544 mTrustAgentService.onConfigure(Collections.EMPTY_LIST, null); 545 } 546 final long maxTimeToLock = dpm.getMaximumTimeToLock(null, mUserId); 547 if (maxTimeToLock != mMaximumTimeToLock) { 548 // If the timeout changes, cancel the alarm and send a timeout event to have 549 // the agent re-evaluate trust. 550 mMaximumTimeToLock = maxTimeToLock; 551 if (mAlarmPendingIntent != null) { 552 mAlarmManager.cancel(mAlarmPendingIntent); 553 mAlarmPendingIntent = null; 554 mHandler.sendEmptyMessage(MSG_TRUST_TIMEOUT); 555 } 556 } 557 } 558 } catch (RemoteException e) { 559 onError(e); 560 } 561 if (mTrustDisabledByDpm != trustDisabled) { 562 mTrustDisabledByDpm = trustDisabled; 563 mTrustManagerService.updateTrust(mUserId, 0); 564 } 565 return trustDisabled; 566 } 567 isTrusted()568 public boolean isTrusted() { 569 return mTrusted && mManagingTrust && !mTrustDisabledByDpm; 570 } 571 isManagingTrust()572 public boolean isManagingTrust() { 573 return mManagingTrust && !mTrustDisabledByDpm; 574 } 575 getMessage()576 public CharSequence getMessage() { 577 return mMessage; 578 } 579 destroy()580 public void destroy() { 581 mHandler.removeMessages(MSG_RESTART_TIMEOUT); 582 583 if (!mBound) { 584 return; 585 } 586 if (DEBUG) Slog.d(TAG, "TrustAgent unbound : " + mName.flattenToShortString()); 587 mTrustManagerService.mArchive.logAgentStopped(mUserId, mName); 588 mContext.unbindService(mConnection); 589 mBound = false; 590 mContext.unregisterReceiver(mBroadcastReceiver); 591 mTrustAgentService = null; 592 mSetTrustAgentFeaturesToken = null; 593 mHandler.sendEmptyMessage(MSG_REVOKE_TRUST); 594 } 595 isConnected()596 public boolean isConnected() { 597 return mTrustAgentService != null; 598 } 599 isBound()600 public boolean isBound() { 601 return mBound; 602 } 603 604 /** 605 * If not connected, returns the time at which the agent is restarted. 606 * 607 * @return restart time in uptime millis. 608 */ getScheduledRestartUptimeMillis()609 public long getScheduledRestartUptimeMillis() { 610 return mScheduledRestartUptimeMillis; 611 } 612 scheduleRestart()613 private void scheduleRestart() { 614 mHandler.removeMessages(MSG_RESTART_TIMEOUT); 615 mScheduledRestartUptimeMillis = SystemClock.uptimeMillis() + RESTART_TIMEOUT_MILLIS; 616 mHandler.sendEmptyMessageAtTime(MSG_RESTART_TIMEOUT, mScheduledRestartUptimeMillis); 617 } 618 } 619