TrustManagerService.java revision abc40bbeeb9d8a183b296a7c7ac3a0c55ed8c636
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 com.android.internal.content.PackageMonitor; 20import com.android.internal.widget.LockPatternUtils; 21import com.android.server.SystemService; 22 23import org.xmlpull.v1.XmlPullParser; 24import org.xmlpull.v1.XmlPullParserException; 25 26import android.Manifest; 27import android.app.ActivityManagerNative; 28import android.app.admin.DevicePolicyManager; 29import android.app.trust.ITrustListener; 30import android.app.trust.ITrustManager; 31import android.content.BroadcastReceiver; 32import android.content.ComponentName; 33import android.content.Context; 34import android.content.Intent; 35import android.content.IntentFilter; 36import android.content.pm.PackageManager; 37import android.content.pm.ResolveInfo; 38import android.content.pm.UserInfo; 39import android.content.res.Resources; 40import android.content.res.TypedArray; 41import android.content.res.XmlResourceParser; 42import android.graphics.drawable.Drawable; 43import android.os.DeadObjectException; 44import android.os.Handler; 45import android.os.IBinder; 46import android.os.Message; 47import android.os.RemoteException; 48import android.os.UserHandle; 49import android.os.UserManager; 50import android.service.trust.TrustAgentService; 51import android.util.ArraySet; 52import android.util.AttributeSet; 53import android.util.Log; 54import android.util.Slog; 55import android.util.SparseBooleanArray; 56import android.util.Xml; 57 58import java.io.FileDescriptor; 59import java.io.IOException; 60import java.io.PrintWriter; 61import java.util.ArrayList; 62import java.util.List; 63 64/** 65 * Manages trust agents and trust listeners. 66 * 67 * It is responsible for binding to the enabled {@link android.service.trust.TrustAgentService}s 68 * of each user and notifies them about events that are relevant to them. 69 * It start and stops them based on the value of 70 * {@link com.android.internal.widget.LockPatternUtils#getEnabledTrustAgents(int)}. 71 * 72 * It also keeps a set of {@link android.app.trust.ITrustListener}s that are notified whenever the 73 * trust state changes for any user. 74 * 75 * Trust state and the setting of enabled agents is kept per user and each user has its own 76 * instance of a {@link android.service.trust.TrustAgentService}. 77 */ 78public class TrustManagerService extends SystemService { 79 80 private static final boolean DEBUG = false; 81 private static final String TAG = "TrustManagerService"; 82 83 private static final Intent TRUST_AGENT_INTENT = 84 new Intent(TrustAgentService.SERVICE_INTERFACE); 85 private static final String PERMISSION_PROVIDE_AGENT = Manifest.permission.PROVIDE_TRUST_AGENT; 86 87 private static final int MSG_REGISTER_LISTENER = 1; 88 private static final int MSG_UNREGISTER_LISTENER = 2; 89 private static final int MSG_DISPATCH_UNLOCK_ATTEMPT = 3; 90 private static final int MSG_ENABLED_AGENTS_CHANGED = 4; 91 92 private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<AgentInfo>(); 93 private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<ITrustListener>(); 94 private final DevicePolicyReceiver mDevicePolicyReceiver = new DevicePolicyReceiver(); 95 private final SparseBooleanArray mUserHasAuthenticatedSinceBoot = new SparseBooleanArray(); 96 /* package */ final TrustArchive mArchive = new TrustArchive(); 97 private final Context mContext; 98 99 private UserManager mUserManager; 100 101 /** 102 * Cache for {@link #refreshAgentList()} 103 */ 104 private final ArraySet<AgentInfo> mObsoleteAgents = new ArraySet<AgentInfo>(); 105 106 107 public TrustManagerService(Context context) { 108 super(context); 109 mContext = context; 110 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 111 } 112 113 @Override 114 public void onStart() { 115 publishBinderService(Context.TRUST_SERVICE, mService); 116 } 117 118 @Override 119 public void onBootPhase(int phase) { 120 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY && !isSafeMode()) { 121 mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true); 122 mDevicePolicyReceiver.register(mContext); 123 refreshAgentList(); 124 } 125 } 126 127 // Agent management 128 129 private static final class AgentInfo { 130 CharSequence label; 131 Drawable icon; 132 ComponentName component; // service that implements ITrustAgent 133 ComponentName settings; // setting to launch to modify agent. 134 TrustAgentWrapper agent; 135 int userId; 136 137 @Override 138 public boolean equals(Object other) { 139 if (!(other instanceof AgentInfo)) { 140 return false; 141 } 142 AgentInfo o = (AgentInfo) other; 143 return component.equals(o.component) && userId == o.userId; 144 } 145 146 @Override 147 public int hashCode() { 148 return component.hashCode() * 31 + userId; 149 } 150 } 151 152 private void updateTrustAll() { 153 List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */); 154 for (UserInfo userInfo : userInfos) { 155 updateTrust(userInfo.id); 156 } 157 } 158 159 public void updateTrust(int userId) { 160 dispatchOnTrustChanged(aggregateIsTrusted(userId), userId); 161 } 162 163 protected void refreshAgentList() { 164 if (DEBUG) Slog.d(TAG, "refreshAgentList()"); 165 PackageManager pm = mContext.getPackageManager(); 166 167 List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */); 168 LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext); 169 170 mObsoleteAgents.clear(); 171 mObsoleteAgents.addAll(mActiveAgents); 172 173 for (UserInfo userInfo : userInfos) { 174 int disabledFeatures = lockPatternUtils.getDevicePolicyManager() 175 .getKeyguardDisabledFeatures(null, userInfo.id); 176 boolean disableTrustAgents = 177 (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0; 178 179 List<ComponentName> enabledAgents = lockPatternUtils.getEnabledTrustAgents(userInfo.id); 180 if (disableTrustAgents || enabledAgents == null) { 181 continue; 182 } 183 List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT, 184 PackageManager.GET_META_DATA, userInfo.id); 185 for (ResolveInfo resolveInfo : resolveInfos) { 186 if (resolveInfo.serviceInfo == null) continue; 187 188 String packageName = resolveInfo.serviceInfo.packageName; 189 // STOPSHIP Reenable this check once the GMS Core prebuild library has the 190 // permission. 191 /* 192 if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName) 193 != PackageManager.PERMISSION_GRANTED) { 194 Log.w(TAG, "Skipping agent because package " + packageName 195 + " does not have permission " + PERMISSION_PROVIDE_AGENT + "."); 196 continue; 197 } 198 */ 199 200 ComponentName name = getComponentName(resolveInfo); 201 if (!enabledAgents.contains(name)) continue; 202 203 AgentInfo agentInfo = new AgentInfo(); 204 agentInfo.component = name; 205 agentInfo.userId = userInfo.id; 206 if (!mActiveAgents.contains(agentInfo)) { 207 agentInfo.label = resolveInfo.loadLabel(pm); 208 agentInfo.icon = resolveInfo.loadIcon(pm); 209 agentInfo.settings = getSettingsComponentName(pm, resolveInfo); 210 agentInfo.agent = new TrustAgentWrapper(mContext, this, 211 new Intent().setComponent(name), userInfo.getUserHandle()); 212 mActiveAgents.add(agentInfo); 213 } else { 214 mObsoleteAgents.remove(agentInfo); 215 } 216 } 217 } 218 219 boolean trustMayHaveChanged = false; 220 for (int i = 0; i < mObsoleteAgents.size(); i++) { 221 AgentInfo info = mObsoleteAgents.valueAt(i); 222 if (info.agent.isTrusted()) { 223 trustMayHaveChanged = true; 224 } 225 info.agent.unbind(); 226 mActiveAgents.remove(info); 227 } 228 229 if (trustMayHaveChanged) { 230 updateTrustAll(); 231 } 232 } 233 234 private ComponentName getSettingsComponentName(PackageManager pm, ResolveInfo resolveInfo) { 235 if (resolveInfo == null || resolveInfo.serviceInfo == null 236 || resolveInfo.serviceInfo.metaData == null) return null; 237 String cn = null; 238 XmlResourceParser parser = null; 239 Exception caughtException = null; 240 try { 241 parser = resolveInfo.serviceInfo.loadXmlMetaData(pm, 242 TrustAgentService.TRUST_AGENT_META_DATA); 243 if (parser == null) { 244 Slog.w(TAG, "Can't find " + TrustAgentService.TRUST_AGENT_META_DATA + " meta-data"); 245 return null; 246 } 247 Resources res = pm.getResourcesForApplication(resolveInfo.serviceInfo.applicationInfo); 248 AttributeSet attrs = Xml.asAttributeSet(parser); 249 int type; 250 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 251 && type != XmlPullParser.START_TAG) { 252 // Drain preamble. 253 } 254 String nodeName = parser.getName(); 255 if (!"trust-agent".equals(nodeName)) { 256 Slog.w(TAG, "Meta-data does not start with trust-agent tag"); 257 return null; 258 } 259 TypedArray sa = res 260 .obtainAttributes(attrs, com.android.internal.R.styleable.TrustAgent); 261 cn = sa.getString(com.android.internal.R.styleable.TrustAgent_settingsActivity); 262 sa.recycle(); 263 } catch (PackageManager.NameNotFoundException e) { 264 caughtException = e; 265 } catch (IOException e) { 266 caughtException = e; 267 } catch (XmlPullParserException e) { 268 caughtException = e; 269 } finally { 270 if (parser != null) parser.close(); 271 } 272 if (caughtException != null) { 273 Slog.w(TAG, "Error parsing : " + resolveInfo.serviceInfo.packageName, caughtException); 274 return null; 275 } 276 if (cn == null) { 277 return null; 278 } 279 if (cn.indexOf('/') < 0) { 280 cn = resolveInfo.serviceInfo.packageName + "/" + cn; 281 } 282 return ComponentName.unflattenFromString(cn); 283 } 284 285 private ComponentName getComponentName(ResolveInfo resolveInfo) { 286 if (resolveInfo == null || resolveInfo.serviceInfo == null) return null; 287 return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name); 288 } 289 290 // Agent dispatch and aggregation 291 292 private boolean aggregateIsTrusted(int userId) { 293 if (!mUserHasAuthenticatedSinceBoot.get(userId)) { 294 return false; 295 } 296 for (int i = 0; i < mActiveAgents.size(); i++) { 297 AgentInfo info = mActiveAgents.valueAt(i); 298 if (info.userId == userId) { 299 if (info.agent.isTrusted()) { 300 return true; 301 } 302 } 303 } 304 return false; 305 } 306 307 private void dispatchUnlockAttempt(boolean successful, int userId) { 308 for (int i = 0; i < mActiveAgents.size(); i++) { 309 AgentInfo info = mActiveAgents.valueAt(i); 310 if (info.userId == userId) { 311 info.agent.onUnlockAttempt(successful); 312 } 313 } 314 315 if (successful && !mUserHasAuthenticatedSinceBoot.get(userId)) { 316 mUserHasAuthenticatedSinceBoot.put(userId, true); 317 updateTrust(userId); 318 } 319 } 320 321 // Listeners 322 323 private void addListener(ITrustListener listener) { 324 for (int i = 0; i < mTrustListeners.size(); i++) { 325 if (mTrustListeners.get(i).asBinder() == listener.asBinder()) { 326 return; 327 } 328 } 329 mTrustListeners.add(listener); 330 } 331 332 private void removeListener(ITrustListener listener) { 333 for (int i = 0; i < mTrustListeners.size(); i++) { 334 if (mTrustListeners.get(i).asBinder() == listener.asBinder()) { 335 mTrustListeners.get(i); 336 return; 337 } 338 } 339 } 340 341 private void dispatchOnTrustChanged(boolean enabled, int userId) { 342 for (int i = 0; i < mTrustListeners.size(); i++) { 343 try { 344 mTrustListeners.get(i).onTrustChanged(enabled, userId); 345 } catch (DeadObjectException e) { 346 if (DEBUG) Slog.d(TAG, "Removing dead TrustListener."); 347 mTrustListeners.remove(i); 348 i--; 349 } catch (RemoteException e) { 350 Slog.e(TAG, "Exception while notifying TrustListener.", e); 351 } 352 } 353 } 354 355 // Plumbing 356 357 private final IBinder mService = new ITrustManager.Stub() { 358 @Override 359 public void reportUnlockAttempt(boolean authenticated, int userId) throws RemoteException { 360 enforceReportPermission(); 361 mHandler.obtainMessage(MSG_DISPATCH_UNLOCK_ATTEMPT, authenticated ? 1 : 0, userId) 362 .sendToTarget(); 363 } 364 365 @Override 366 public void reportEnabledTrustAgentsChanged(int userId) throws RemoteException { 367 enforceReportPermission(); 368 // coalesce refresh messages. 369 mHandler.removeMessages(MSG_ENABLED_AGENTS_CHANGED); 370 mHandler.sendEmptyMessage(MSG_ENABLED_AGENTS_CHANGED); 371 } 372 373 @Override 374 public void registerTrustListener(ITrustListener trustListener) throws RemoteException { 375 enforceListenerPermission(); 376 mHandler.obtainMessage(MSG_REGISTER_LISTENER, trustListener).sendToTarget(); 377 } 378 379 @Override 380 public void unregisterTrustListener(ITrustListener trustListener) throws RemoteException { 381 enforceListenerPermission(); 382 mHandler.obtainMessage(MSG_UNREGISTER_LISTENER, trustListener).sendToTarget(); 383 } 384 385 private void enforceReportPermission() { 386 mContext.enforceCallingPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, 387 "reporting trust events"); 388 } 389 390 private void enforceListenerPermission() { 391 mContext.enforceCallingPermission(Manifest.permission.TRUST_LISTENER, 392 "register trust listener"); 393 } 394 395 @Override 396 protected void dump(FileDescriptor fd, final PrintWriter fout, String[] args) { 397 mContext.enforceCallingPermission(Manifest.permission.DUMP, 398 "dumping TrustManagerService"); 399 final UserInfo currentUser; 400 final List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */); 401 try { 402 currentUser = ActivityManagerNative.getDefault().getCurrentUser(); 403 } catch (RemoteException e) { 404 throw new RuntimeException(e); 405 } 406 mHandler.runWithScissors(new Runnable() { 407 @Override 408 public void run() { 409 fout.println("Trust manager state:"); 410 for (UserInfo user : userInfos) { 411 dumpUser(fout, user, user.id == currentUser.id); 412 } 413 } 414 }, 1500); 415 } 416 417 private void dumpUser(PrintWriter fout, UserInfo user, boolean isCurrent) { 418 fout.printf(" User \"%s\" (id=%d, flags=%#x)", 419 user.name, user.id, user.flags); 420 if (isCurrent) { 421 fout.print(" (current)"); 422 } 423 fout.print(": trusted=" + dumpBool(aggregateIsTrusted(user.id))); 424 fout.println(); 425 fout.println(" Enabled agents:"); 426 boolean duplicateSimpleNames = false; 427 ArraySet<String> simpleNames = new ArraySet<String>(); 428 for (AgentInfo info : mActiveAgents) { 429 if (info.userId != user.id) { continue; } 430 boolean trusted = info.agent.isTrusted(); 431 fout.print(" "); fout.println(info.component.flattenToShortString()); 432 fout.print(" connected=" + dumpBool(info.agent.isConnected())); 433 fout.println(", trusted=" + dumpBool(trusted)); 434 if (trusted) { 435 fout.println(" message=\"" + info.agent.getMessage() + "\""); 436 } 437 if (!simpleNames.add(TrustArchive.getSimpleName(info.component))) { 438 duplicateSimpleNames = true; 439 } 440 } 441 fout.println(" Events:"); 442 mArchive.dump(fout, 50, user.id, " " /* linePrefix */, duplicateSimpleNames); 443 fout.println(); 444 } 445 446 private String dumpBool(boolean b) { 447 return b ? "1" : "0"; 448 } 449 }; 450 451 private final Handler mHandler = new Handler() { 452 @Override 453 public void handleMessage(Message msg) { 454 switch (msg.what) { 455 case MSG_REGISTER_LISTENER: 456 addListener((ITrustListener) msg.obj); 457 break; 458 case MSG_UNREGISTER_LISTENER: 459 removeListener((ITrustListener) msg.obj); 460 break; 461 case MSG_DISPATCH_UNLOCK_ATTEMPT: 462 dispatchUnlockAttempt(msg.arg1 != 0, msg.arg2); 463 break; 464 case MSG_ENABLED_AGENTS_CHANGED: 465 refreshAgentList(); 466 break; 467 } 468 } 469 }; 470 471 private final PackageMonitor mPackageMonitor = new PackageMonitor() { 472 @Override 473 public void onSomePackagesChanged() { 474 refreshAgentList(); 475 } 476 477 @Override 478 public boolean onPackageChanged(String packageName, int uid, String[] components) { 479 // We're interested in all changes, even if just some components get enabled / disabled. 480 return true; 481 } 482 }; 483 484 private class DevicePolicyReceiver extends BroadcastReceiver { 485 486 @Override 487 public void onReceive(Context context, Intent intent) { 488 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals( 489 intent.getAction())) { 490 refreshAgentList(); 491 } 492 } 493 494 public void register(Context context) { 495 context.registerReceiverAsUser(this, 496 UserHandle.ALL, 497 new IntentFilter( 498 DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED), 499 null /* permission */, 500 null /* scheduler */); 501 } 502 } 503} 504