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 android.content.ComponentName; 20import android.os.SystemClock; 21import android.os.UserHandle; 22import android.service.trust.TrustAgentService; 23import android.util.TimeUtils; 24 25import java.io.PrintWriter; 26import java.util.ArrayDeque; 27import java.util.Iterator; 28 29/** 30 * An archive of trust events. 31 */ 32public class TrustArchive { 33 private static final int TYPE_GRANT_TRUST = 0; 34 private static final int TYPE_REVOKE_TRUST = 1; 35 private static final int TYPE_TRUST_TIMEOUT = 2; 36 private static final int TYPE_AGENT_DIED = 3; 37 private static final int TYPE_AGENT_CONNECTED = 4; 38 private static final int TYPE_AGENT_STOPPED = 5; 39 private static final int TYPE_MANAGING_TRUST = 6; 40 41 private static final int HISTORY_LIMIT = 200; 42 43 private static class Event { 44 final int type; 45 final int userId; 46 final ComponentName agent; 47 final long elapsedTimestamp; 48 49 // grantTrust 50 final String message; 51 final long duration; 52 final int flags; 53 54 // managingTrust 55 final boolean managingTrust; 56 57 private Event(int type, int userId, ComponentName agent, String message, 58 long duration, int flags, boolean managingTrust) { 59 this.type = type; 60 this.userId = userId; 61 this.agent = agent; 62 this.elapsedTimestamp = SystemClock.elapsedRealtime(); 63 this.message = message; 64 this.duration = duration; 65 this.flags = flags; 66 this.managingTrust = managingTrust; 67 } 68 } 69 70 ArrayDeque<Event> mEvents = new ArrayDeque<Event>(); 71 72 public void logGrantTrust(int userId, ComponentName agent, String message, 73 long duration, int flags) { 74 addEvent(new Event(TYPE_GRANT_TRUST, userId, agent, message, duration, 75 flags, false)); 76 } 77 78 public void logRevokeTrust(int userId, ComponentName agent) { 79 addEvent(new Event(TYPE_REVOKE_TRUST, userId, agent, null, 0, 0, false)); 80 } 81 82 public void logTrustTimeout(int userId, ComponentName agent) { 83 addEvent(new Event(TYPE_TRUST_TIMEOUT, userId, agent, null, 0, 0, false)); 84 } 85 86 public void logAgentDied(int userId, ComponentName agent) { 87 addEvent(new Event(TYPE_AGENT_DIED, userId, agent, null, 0, 0, false)); 88 } 89 90 public void logAgentConnected(int userId, ComponentName agent) { 91 addEvent(new Event(TYPE_AGENT_CONNECTED, userId, agent, null, 0, 0, false)); 92 } 93 94 public void logAgentStopped(int userId, ComponentName agent) { 95 addEvent(new Event(TYPE_AGENT_STOPPED, userId, agent, null, 0, 0, false)); 96 } 97 98 public void logManagingTrust(int userId, ComponentName agent, boolean managing) { 99 addEvent(new Event(TYPE_MANAGING_TRUST, userId, agent, null, 0, 0, managing)); 100 } 101 102 private void addEvent(Event e) { 103 if (mEvents.size() >= HISTORY_LIMIT) { 104 mEvents.removeFirst(); 105 } 106 mEvents.addLast(e); 107 } 108 109 public void dump(PrintWriter writer, int limit, int userId, String linePrefix, 110 boolean duplicateSimpleNames) { 111 int count = 0; 112 Iterator<Event> iter = mEvents.descendingIterator(); 113 while (iter.hasNext() && count < limit) { 114 Event ev = iter.next(); 115 if (userId != UserHandle.USER_ALL && userId != ev.userId) { 116 continue; 117 } 118 119 writer.print(linePrefix); 120 writer.printf("#%-2d %s %s: ", count, formatElapsed(ev.elapsedTimestamp), 121 dumpType(ev.type)); 122 if (userId == UserHandle.USER_ALL) { 123 writer.print("user="); writer.print(ev.userId); writer.print(", "); 124 } 125 writer.print("agent="); 126 if (duplicateSimpleNames) { 127 writer.print(ev.agent.flattenToShortString()); 128 } else { 129 writer.print(getSimpleName(ev.agent)); 130 } 131 switch (ev.type) { 132 case TYPE_GRANT_TRUST: 133 writer.printf(", message=\"%s\", duration=%s, flags=%s", 134 ev.message, formatDuration(ev.duration), dumpGrantFlags(ev.flags)); 135 break; 136 case TYPE_MANAGING_TRUST: 137 writer.printf(", managingTrust=" + ev.managingTrust); 138 break; 139 default: 140 } 141 writer.println(); 142 count++; 143 } 144 } 145 146 public static String formatDuration(long duration) { 147 StringBuilder sb = new StringBuilder(); 148 TimeUtils.formatDuration(duration, sb); 149 return sb.toString(); 150 } 151 152 private static String formatElapsed(long elapsed) { 153 long delta = elapsed - SystemClock.elapsedRealtime(); 154 long wallTime = delta + System.currentTimeMillis(); 155 return TimeUtils.logTimeOfDay(wallTime); 156 } 157 158 /* package */ static String getSimpleName(ComponentName cn) { 159 String name = cn.getClassName(); 160 int idx = name.lastIndexOf('.'); 161 if (idx < name.length() && idx >= 0) { 162 return name.substring(idx + 1); 163 } else { 164 return name; 165 } 166 } 167 168 private String dumpType(int type) { 169 switch (type) { 170 case TYPE_GRANT_TRUST: 171 return "GrantTrust"; 172 case TYPE_REVOKE_TRUST: 173 return "RevokeTrust"; 174 case TYPE_TRUST_TIMEOUT: 175 return "TrustTimeout"; 176 case TYPE_AGENT_DIED: 177 return "AgentDied"; 178 case TYPE_AGENT_CONNECTED: 179 return "AgentConnected"; 180 case TYPE_AGENT_STOPPED: 181 return "AgentStopped"; 182 case TYPE_MANAGING_TRUST: 183 return "ManagingTrust"; 184 default: 185 return "Unknown(" + type + ")"; 186 } 187 } 188 189 private String dumpGrantFlags(int flags) { 190 StringBuilder sb = new StringBuilder(); 191 if ((flags & TrustAgentService.FLAG_GRANT_TRUST_INITIATED_BY_USER) != 0) { 192 if (sb.length() != 0) sb.append('|'); 193 sb.append("INITIATED_BY_USER"); 194 } 195 if ((flags & TrustAgentService.FLAG_GRANT_TRUST_DISMISS_KEYGUARD) != 0) { 196 if (sb.length() != 0) sb.append('|'); 197 sb.append("DISMISS_KEYGUARD"); 198 } 199 if (sb.length() == 0) { 200 sb.append('0'); 201 } 202 return sb.toString(); 203 } 204} 205