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 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 Log.v(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.v(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 destroy(); 164 mTrustManagerService.resetAgent(mName, mUserId); 165 break; 166 case MSG_SET_TRUST_AGENT_FEATURES_COMPLETED: 167 IBinder token = (IBinder) msg.obj; 168 boolean result = msg.arg1 != 0; 169 if (mSetTrustAgentFeaturesToken == token) { 170 mSetTrustAgentFeaturesToken = null; 171 if (mTrustDisabledByDpm && result) { 172 if (DEBUG) Log.v(TAG, "Re-enabling agent because it acknowledged " 173 + "enabled features: " + mName); 174 mTrustDisabledByDpm = false; 175 mTrustManagerService.updateTrust(mUserId, 0); 176 } 177 } else { 178 if (DEBUG) Log.w(TAG, "Ignoring MSG_SET_TRUST_AGENT_FEATURES_COMPLETED " 179 + "with obsolete token: " + mName); 180 } 181 break; 182 case MSG_MANAGING_TRUST: 183 mManagingTrust = msg.arg1 != 0; 184 if (!mManagingTrust) { 185 mTrusted = false; 186 mMessage = null; 187 } 188 mTrustManagerService.mArchive.logManagingTrust(mUserId, mName, mManagingTrust); 189 mTrustManagerService.updateTrust(mUserId, 0); 190 break; 191 } 192 } 193 }; 194 195 private ITrustAgentServiceCallback mCallback = new ITrustAgentServiceCallback.Stub() { 196 197 @Override 198 public void grantTrust(CharSequence userMessage, long durationMs, int flags) { 199 if (DEBUG) Slog.v(TAG, "enableTrust(" + userMessage + ", durationMs = " + durationMs 200 + ", flags = " + flags + ")"); 201 202 Message msg = mHandler.obtainMessage( 203 MSG_GRANT_TRUST, flags, 0, userMessage); 204 msg.getData().putLong(DATA_DURATION, durationMs); 205 msg.sendToTarget(); 206 } 207 208 @Override 209 public void revokeTrust() { 210 if (DEBUG) Slog.v(TAG, "revokeTrust()"); 211 mHandler.sendEmptyMessage(MSG_REVOKE_TRUST); 212 } 213 214 @Override 215 public void setManagingTrust(boolean managingTrust) { 216 if (DEBUG) Slog.v(TAG, "managingTrust()"); 217 mHandler.obtainMessage(MSG_MANAGING_TRUST, managingTrust ? 1 : 0, 0).sendToTarget(); 218 } 219 220 @Override 221 public void onConfigureCompleted(boolean result, IBinder token) { 222 if (DEBUG) Slog.v(TAG, "onSetTrustAgentFeaturesEnabledCompleted(result=" + result); 223 mHandler.obtainMessage(MSG_SET_TRUST_AGENT_FEATURES_COMPLETED, 224 result ? 1 : 0, 0, token).sendToTarget(); 225 } 226 }; 227 228 private final ServiceConnection mConnection = new ServiceConnection() { 229 @Override 230 public void onServiceConnected(ComponentName name, IBinder service) { 231 if (DEBUG) Log.v(TAG, "TrustAgent started : " + name.flattenToString()); 232 mHandler.removeMessages(MSG_RESTART_TIMEOUT); 233 mTrustAgentService = ITrustAgentService.Stub.asInterface(service); 234 mTrustManagerService.mArchive.logAgentConnected(mUserId, name); 235 setCallback(mCallback); 236 updateDevicePolicyFeatures(); 237 238 if (mPendingSuccessfulUnlock) { 239 onUnlockAttempt(true); 240 mPendingSuccessfulUnlock = false; 241 } 242 243 if (mTrustManagerService.isDeviceLockedInner(mUserId)) { 244 onDeviceLocked(); 245 } else { 246 onDeviceUnlocked(); 247 } 248 } 249 250 @Override 251 public void onServiceDisconnected(ComponentName name) { 252 if (DEBUG) Log.v(TAG, "TrustAgent disconnected : " + name.flattenToShortString()); 253 mTrustAgentService = null; 254 mManagingTrust = false; 255 mSetTrustAgentFeaturesToken = null; 256 mTrustManagerService.mArchive.logAgentDied(mUserId, name); 257 mHandler.sendEmptyMessage(MSG_REVOKE_TRUST); 258 if (mBound) { 259 scheduleRestart(); 260 } 261 // mTrustDisabledByDpm maintains state 262 } 263 }; 264 265 public TrustAgentWrapper(Context context, TrustManagerService trustManagerService, 266 Intent intent, UserHandle user) { 267 mContext = context; 268 mTrustManagerService = trustManagerService; 269 mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); 270 mUserId = user.getIdentifier(); 271 mName = intent.getComponent(); 272 273 mAlarmIntent = new Intent(TRUST_EXPIRED_ACTION).putExtra(EXTRA_COMPONENT_NAME, mName); 274 mAlarmIntent.setData(Uri.parse(mAlarmIntent.toUri(Intent.URI_INTENT_SCHEME))); 275 mAlarmIntent.setPackage(context.getPackageName()); 276 277 final IntentFilter alarmFilter = new IntentFilter(TRUST_EXPIRED_ACTION); 278 alarmFilter.addDataScheme(mAlarmIntent.getScheme()); 279 final String pathUri = mAlarmIntent.toUri(Intent.URI_INTENT_SCHEME); 280 alarmFilter.addDataPath(pathUri, PatternMatcher.PATTERN_LITERAL); 281 282 // Schedules a restart for when connecting times out. If the connection succeeds, 283 // the restart is canceled in mCallback's onConnected. 284 scheduleRestart(); 285 mBound = context.bindServiceAsUser(intent, mConnection, 286 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, user); 287 if (mBound) { 288 mContext.registerReceiver(mBroadcastReceiver, alarmFilter, PERMISSION, null); 289 } else { 290 Log.e(TAG, "Can't bind to TrustAgent " + mName.flattenToShortString()); 291 } 292 } 293 294 private void onError(Exception e) { 295 Slog.w(TAG , "Remote Exception", e); 296 } 297 298 private void onTrustTimeout() { 299 try { 300 if (mTrustAgentService != null) mTrustAgentService.onTrustTimeout(); 301 } catch (RemoteException e) { 302 onError(e); 303 } 304 } 305 306 /** 307 * @see android.service.trust.TrustAgentService#onUnlockAttempt(boolean) 308 */ 309 public void onUnlockAttempt(boolean successful) { 310 try { 311 if (mTrustAgentService != null) { 312 mTrustAgentService.onUnlockAttempt(successful); 313 } else { 314 mPendingSuccessfulUnlock = successful; 315 } 316 } catch (RemoteException e) { 317 onError(e); 318 } 319 } 320 321 /** 322 * @see android.service.trust.TrustAgentService#onDeviceLocked() 323 */ 324 public void onDeviceLocked() { 325 try { 326 if (mTrustAgentService != null) mTrustAgentService.onDeviceLocked(); 327 } catch (RemoteException e) { 328 onError(e); 329 } 330 } 331 332 /** 333 * @see android.service.trust.TrustAgentService#onDeviceUnlocked() 334 */ 335 public void onDeviceUnlocked() { 336 try { 337 if (mTrustAgentService != null) mTrustAgentService.onDeviceUnlocked(); 338 } catch (RemoteException e) { 339 onError(e); 340 } 341 } 342 343 private void setCallback(ITrustAgentServiceCallback callback) { 344 try { 345 if (mTrustAgentService != null) { 346 mTrustAgentService.setCallback(callback); 347 } 348 } catch (RemoteException e) { 349 onError(e); 350 } 351 } 352 353 boolean updateDevicePolicyFeatures() { 354 boolean trustDisabled = false; 355 if (DEBUG) Slog.v(TAG, "updateDevicePolicyFeatures(" + mName + ")"); 356 try { 357 if (mTrustAgentService != null) { 358 DevicePolicyManager dpm = 359 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); 360 361 if ((dpm.getKeyguardDisabledFeatures(null, mUserId) 362 & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0) { 363 List<PersistableBundle> config = dpm.getTrustAgentConfiguration( 364 null, mName, mUserId); 365 trustDisabled = true; 366 if (DEBUG) Slog.v(TAG, "Detected trust agents disabled. Config = " + config); 367 if (config != null && config.size() > 0) { 368 if (DEBUG) { 369 Slog.v(TAG, "TrustAgent " + mName.flattenToShortString() 370 + " disabled until it acknowledges "+ config); 371 } 372 mSetTrustAgentFeaturesToken = new Binder(); 373 mTrustAgentService.onConfigure(config, mSetTrustAgentFeaturesToken); 374 } 375 } else { 376 mTrustAgentService.onConfigure(Collections.EMPTY_LIST, null); 377 } 378 final long maxTimeToLock = dpm.getMaximumTimeToLockForUserAndProfiles(mUserId); 379 if (maxTimeToLock != mMaximumTimeToLock) { 380 // If the timeout changes, cancel the alarm and send a timeout event to have 381 // the agent re-evaluate trust. 382 mMaximumTimeToLock = maxTimeToLock; 383 if (mAlarmPendingIntent != null) { 384 mAlarmManager.cancel(mAlarmPendingIntent); 385 mAlarmPendingIntent = null; 386 mHandler.sendEmptyMessage(MSG_TRUST_TIMEOUT); 387 } 388 } 389 } 390 } catch (RemoteException e) { 391 onError(e); 392 } 393 if (mTrustDisabledByDpm != trustDisabled) { 394 mTrustDisabledByDpm = trustDisabled; 395 mTrustManagerService.updateTrust(mUserId, 0); 396 } 397 return trustDisabled; 398 } 399 400 public boolean isTrusted() { 401 return mTrusted && mManagingTrust && !mTrustDisabledByDpm; 402 } 403 404 public boolean isManagingTrust() { 405 return mManagingTrust && !mTrustDisabledByDpm; 406 } 407 408 public CharSequence getMessage() { 409 return mMessage; 410 } 411 412 public void destroy() { 413 mHandler.removeMessages(MSG_RESTART_TIMEOUT); 414 415 if (!mBound) { 416 return; 417 } 418 if (DEBUG) Log.v(TAG, "TrustAgent unbound : " + mName.flattenToShortString()); 419 mTrustManagerService.mArchive.logAgentStopped(mUserId, mName); 420 mContext.unbindService(mConnection); 421 mBound = false; 422 mContext.unregisterReceiver(mBroadcastReceiver); 423 mTrustAgentService = null; 424 mSetTrustAgentFeaturesToken = null; 425 mHandler.sendEmptyMessage(MSG_REVOKE_TRUST); 426 } 427 428 public boolean isConnected() { 429 return mTrustAgentService != null; 430 } 431 432 public boolean isBound() { 433 return mBound; 434 } 435 436 /** 437 * If not connected, returns the time at which the agent is restarted. 438 * 439 * @return restart time in uptime millis. 440 */ 441 public long getScheduledRestartUptimeMillis() { 442 return mScheduledRestartUptimeMillis; 443 } 444 445 private void scheduleRestart() { 446 mHandler.removeMessages(MSG_RESTART_TIMEOUT); 447 mScheduledRestartUptimeMillis = SystemClock.uptimeMillis() + RESTART_TIMEOUT_MILLIS; 448 mHandler.sendEmptyMessageAtTime(MSG_RESTART_TIMEOUT, mScheduledRestartUptimeMillis); 449 } 450} 451