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