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