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