diff options
author | Adrian Roos <roosa@google.com> | 2014-05-21 13:44:06 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-05-21 13:44:07 +0000 |
commit | efb5d8d317b3aedc360a05cfb366f703c12f1c23 (patch) | |
tree | 7a1751c6a739599eebfbe63b2014c9c34ce3b4aa /services | |
parent | b979f23c5970138d75d5c2e76ded1470f7a8eb83 (diff) | |
parent | 7a4f3d448b17b4bea190c906d7ecc7f8bec9ff80 (diff) | |
download | frameworks_base-efb5d8d317b3aedc360a05cfb366f703c12f1c23.zip frameworks_base-efb5d8d317b3aedc360a05cfb366f703c12f1c23.tar.gz frameworks_base-efb5d8d317b3aedc360a05cfb366f703c12f1c23.tar.bz2 |
Merge "Add dumpsys facility and a history to TrustManagerService"
Diffstat (limited to 'services')
3 files changed, 248 insertions, 10 deletions
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java index d8d3da1..47ce3b6 100644 --- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java +++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java @@ -20,7 +20,6 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; @@ -39,10 +38,15 @@ public class TrustAgentWrapper { private static final boolean DEBUG = false; private static final String TAG = "TrustAgentWrapper"; - private static final int MSG_ENABLE_TRUST = 1; + private static final int MSG_GRANT_TRUST = 1; private static final int MSG_REVOKE_TRUST = 2; private static final int MSG_TRUST_TIMEOUT = 3; + /** + * Long extra for {@link #MSG_GRANT_TRUST} + */ + private static final String DATA_DURATION = "duration"; + private final TrustManagerService mTrustManagerService; private final int mUserId; private final Context mContext; @@ -58,19 +62,32 @@ public class TrustAgentWrapper { @Override public void handleMessage(Message msg) { switch (msg.what) { - case MSG_ENABLE_TRUST: + case MSG_GRANT_TRUST: mTrusted = true; mMessage = (CharSequence) msg.obj; boolean initiatedByUser = msg.arg1 != 0; - // TODO: Handle handle user initiated trust changes. + // TODO: Handle initiatedByUser. + long durationMs = msg.getData().getLong(DATA_DURATION); + if (durationMs > 0) { + mHandler.removeMessages(MSG_TRUST_TIMEOUT); + mHandler.sendEmptyMessageDelayed(MSG_TRUST_TIMEOUT, durationMs); + } + mTrustManagerService.mArchive.logGrantTrust(mUserId, mName, + (mMessage != null ? mMessage.toString() : null), + durationMs, initiatedByUser); mTrustManagerService.updateTrust(mUserId); break; case MSG_TRUST_TIMEOUT: if (DEBUG) Slog.v(TAG, "Trust timed out : " + mName.flattenToShortString()); + mTrustManagerService.mArchive.logTrustTimeout(mUserId, mName); // Fall through. case MSG_REVOKE_TRUST: mTrusted = false; mMessage = null; + mHandler.removeMessages(MSG_TRUST_TIMEOUT); + if (msg.what == MSG_REVOKE_TRUST) { + mTrustManagerService.mArchive.logRevokeTrust(mUserId, mName); + } mTrustManagerService.updateTrust(mUserId); break; } @@ -84,12 +101,10 @@ public class TrustAgentWrapper { if (DEBUG) Slog.v(TAG, "enableTrust(" + userMessage + ", durationMs = " + durationMs + ", initiatedByUser = " + initiatedByUser + ")"); - mHandler.obtainMessage(MSG_ENABLE_TRUST, initiatedByUser ? 1 : 0, 0, userMessage) - .sendToTarget(); - if (durationMs > 0) { - mHandler.removeMessages(MSG_TRUST_TIMEOUT); - mHandler.sendEmptyMessageDelayed(MSG_TRUST_TIMEOUT, durationMs); - } + Message msg = mHandler.obtainMessage( + MSG_GRANT_TRUST, initiatedByUser ? 1 : 0, 0, userMessage); + msg.getData().putLong(DATA_DURATION, durationMs); + msg.sendToTarget(); } @Override @@ -111,6 +126,7 @@ public class TrustAgentWrapper { public void onServiceDisconnected(ComponentName name) { if (DEBUG) Log.v(TAG, "TrustAgent disconnected : " + name.flattenToShortString()); mTrustAgentService = null; + mTrustManagerService.mArchive.logAgentDied(mUserId, name); mHandler.sendEmptyMessage(MSG_REVOKE_TRUST); } }; @@ -165,4 +181,8 @@ public class TrustAgentWrapper { if (DEBUG) Log.v(TAG, "TrustAgent unbound : " + mName.flattenToShortString()); mContext.unbindService(mConnection); } + + public boolean isConnected() { + return mTrustAgentService != null; + } } diff --git a/services/core/java/com/android/server/trust/TrustArchive.java b/services/core/java/com/android/server/trust/TrustArchive.java new file mode 100644 index 0000000..aad156c --- /dev/null +++ b/services/core/java/com/android/server/trust/TrustArchive.java @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server.trust; + +import android.content.ComponentName; +import android.os.SystemClock; +import android.os.UserHandle; +import android.util.TimeUtils; + +import java.io.PrintWriter; +import java.util.ArrayDeque; +import java.util.Iterator; + +/** + * An archive of trust events. + */ +public class TrustArchive { + private static final int TYPE_GRANT_TRUST = 0; + private static final int TYPE_REVOKE_TRUST = 1; + private static final int TYPE_TRUST_TIMEOUT = 2; + private static final int TYPE_AGENT_DIED = 3; + + private static final int HISTORY_LIMIT = 200; + + private static class Event { + final int type; + final int userId; + final ComponentName agent; + final long elapsedTimestamp; + + // grantTrust + final String message; + final long duration; + final boolean userInitiated; + + private Event(int type, int userId, ComponentName agent, String message, + long duration, boolean userInitiated) { + this.type = type; + this.userId = userId; + this.agent = agent; + this.elapsedTimestamp = SystemClock.elapsedRealtime(); + this.message = message; + this.duration = duration; + this.userInitiated = userInitiated; + } + } + + ArrayDeque<Event> mEvents = new ArrayDeque<Event>(); + + public void logGrantTrust(int userId, ComponentName agent, String message, + long duration, boolean userInitiated) { + addEvent(new Event(TYPE_GRANT_TRUST, userId, agent, message, duration, + userInitiated)); + } + + public void logRevokeTrust(int userId, ComponentName agent) { + addEvent(new Event(TYPE_REVOKE_TRUST, userId, agent, null, 0, false)); + } + + public void logTrustTimeout(int userId, ComponentName agent) { + addEvent(new Event(TYPE_TRUST_TIMEOUT, userId, agent, null, 0, false)); + } + + public void logAgentDied(int userId, ComponentName agent) { + addEvent(new Event(TYPE_AGENT_DIED, userId, agent, null, 0, false)); + } + + private void addEvent(Event e) { + if (mEvents.size() >= HISTORY_LIMIT) { + mEvents.removeFirst(); + } + mEvents.addLast(e); + } + + public void dump(PrintWriter writer, int limit, int userId, String linePrefix, + boolean duplicateSimpleNames) { + int count = 0; + Iterator<Event> iter = mEvents.descendingIterator(); + while (iter.hasNext() && count < limit) { + Event ev = iter.next(); + if (userId != UserHandle.USER_ALL && userId != ev.userId) { + continue; + } + + writer.print(linePrefix); + writer.printf("#%-2d %s %s: ", count, formatElapsed(ev.elapsedTimestamp), + dumpType(ev.type)); + if (userId == UserHandle.USER_ALL) { + writer.print("user="); writer.print(ev.userId); writer.print(", "); + } + writer.print("agent="); + if (duplicateSimpleNames) { + writer.print(ev.agent.flattenToShortString()); + } else { + writer.print(getSimpleName(ev.agent)); + } + switch (ev.type) { + case TYPE_GRANT_TRUST: + writer.printf(", message=\"%s\", duration=%s", + ev.message, formatDuration(ev.duration)); + break; + default: + } + writer.println(); + count++; + } + } + + private static String formatDuration(long duration) { + StringBuilder sb = new StringBuilder(); + TimeUtils.formatDuration(duration, sb); + return sb.toString(); + } + + private static String formatElapsed(long elapsed) { + long delta = elapsed - SystemClock.elapsedRealtime(); + long wallTime = delta + System.currentTimeMillis(); + return TimeUtils.logTimeOfDay(wallTime); + } + + /* package */ static String getSimpleName(ComponentName cn) { + String name = cn.getClassName(); + int idx = name.lastIndexOf('.'); + if (idx < name.length() && idx >= 0) { + return name.substring(idx + 1); + } else { + return name; + } + } + + private String dumpType(int type) { + switch (type) { + case TYPE_GRANT_TRUST: + return "GrantTrust"; + case TYPE_REVOKE_TRUST: + return "RevokeTrust"; + case TYPE_TRUST_TIMEOUT: + return "TrustTimeout"; + case TYPE_AGENT_DIED: + return "AgentDied"; + default: + return "Unknown(" + type + ")"; + } + } +} diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index efaa91b..986cdc1 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -24,6 +24,7 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import android.Manifest; +import android.app.ActivityManagerNative; import android.app.admin.DevicePolicyManager; import android.app.trust.ITrustListener; import android.app.trust.ITrustManager; @@ -52,7 +53,9 @@ import android.util.Slog; import android.util.SparseBooleanArray; import android.util.Xml; +import java.io.FileDescriptor; import java.io.IOException; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; @@ -87,6 +90,7 @@ public class TrustManagerService extends SystemService { private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<ITrustListener>(); private final DevicePolicyReceiver mDevicePolicyReceiver = new DevicePolicyReceiver(); private final SparseBooleanArray mUserHasAuthenticatedSinceBoot = new SparseBooleanArray(); + /* package */ final TrustArchive mArchive = new TrustArchive(); private final Context mContext; private UserManager mUserManager; @@ -367,6 +371,61 @@ public class TrustManagerService extends SystemService { mContext.enforceCallingPermission(Manifest.permission.TRUST_LISTENER, "register trust listener"); } + + @Override + protected void dump(FileDescriptor fd, final PrintWriter fout, String[] args) { + mContext.enforceCallingPermission(Manifest.permission.DUMP, + "dumping TrustManagerService"); + final UserInfo currentUser; + final List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */); + try { + currentUser = ActivityManagerNative.getDefault().getCurrentUser(); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + mHandler.runWithScissors(new Runnable() { + @Override + public void run() { + fout.println("Trust manager state:"); + for (UserInfo user : userInfos) { + dumpUser(fout, user, user.id == currentUser.id); + } + } + }, 1500); + } + + private void dumpUser(PrintWriter fout, UserInfo user, boolean isCurrent) { + fout.printf(" User \"%s\" (id=%d, flags=%#x)", + user.name, user.id, user.flags); + if (isCurrent) { + fout.print(" (current)"); + } + fout.print(": trusted=" + dumpBool(aggregateIsTrusted(user.id))); + fout.println(); + fout.println(" Enabled agents:"); + boolean duplicateSimpleNames = false; + ArraySet<String> simpleNames = new ArraySet<String>(); + for (AgentInfo info : mActiveAgents) { + if (info.userId != user.id) { continue; } + boolean trusted = info.agent.isTrusted(); + fout.print(" "); fout.println(info.component.flattenToShortString()); + fout.print(" connected=" + dumpBool(info.agent.isConnected())); + fout.println(", trusted=" + dumpBool(trusted)); + if (trusted) { + fout.println(" message=\"" + info.agent.getMessage() + "\""); + } + if (!simpleNames.add(TrustArchive.getSimpleName(info.component))) { + duplicateSimpleNames = true; + } + } + fout.println(" Events:"); + mArchive.dump(fout, 50, user.id, " " /* linePrefix */, duplicateSimpleNames); + fout.println(); + } + + private String dumpBool(boolean b) { + return b ? "1" : "0"; + } }; private final Handler mHandler = new Handler() { |