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