Loading services/core/java/com/android/server/trust/TrustAgentWrapper.java +30 −10 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; } Loading @@ -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 Loading @@ -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); } }; Loading Loading @@ -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; } } services/core/java/com/android/server/trust/TrustArchive.java 0 → 100644 +159 −0 Original line number Diff line number Diff line /* * 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 + ")"; } } } services/core/java/com/android/server/trust/TrustManagerService.java +59 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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() { Loading Loading
services/core/java/com/android/server/trust/TrustAgentWrapper.java +30 −10 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; } Loading @@ -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 Loading @@ -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); } }; Loading Loading @@ -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; } }
services/core/java/com/android/server/trust/TrustArchive.java 0 → 100644 +159 −0 Original line number Diff line number Diff line /* * 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 + ")"; } } }
services/core/java/com/android/server/trust/TrustManagerService.java +59 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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() { Loading