blob: aaac2979049b4bd0ee79edc5dfb36a59f30298df [file] [log] [blame]
/*
* 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.service.trust.TrustAgentService;
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 TYPE_AGENT_CONNECTED = 4;
private static final int TYPE_AGENT_STOPPED = 5;
private static final int TYPE_MANAGING_TRUST = 6;
private static final int TYPE_POLICY_CHANGED = 7;
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 int flags;
// managingTrust
final boolean managingTrust;
private Event(int type, int userId, ComponentName agent, String message,
long duration, int flags, boolean managingTrust) {
this.type = type;
this.userId = userId;
this.agent = agent;
this.elapsedTimestamp = SystemClock.elapsedRealtime();
this.message = message;
this.duration = duration;
this.flags = flags;
this.managingTrust = managingTrust;
}
}
ArrayDeque<Event> mEvents = new ArrayDeque<Event>();
public void logGrantTrust(int userId, ComponentName agent, String message,
long duration, int flags) {
addEvent(new Event(TYPE_GRANT_TRUST, userId, agent, message, duration,
flags, false));
}
public void logRevokeTrust(int userId, ComponentName agent) {
addEvent(new Event(TYPE_REVOKE_TRUST, userId, agent, null, 0, 0, false));
}
public void logTrustTimeout(int userId, ComponentName agent) {
addEvent(new Event(TYPE_TRUST_TIMEOUT, userId, agent, null, 0, 0, false));
}
public void logAgentDied(int userId, ComponentName agent) {
addEvent(new Event(TYPE_AGENT_DIED, userId, agent, null, 0, 0, false));
}
public void logAgentConnected(int userId, ComponentName agent) {
addEvent(new Event(TYPE_AGENT_CONNECTED, userId, agent, null, 0, 0, false));
}
public void logAgentStopped(int userId, ComponentName agent) {
addEvent(new Event(TYPE_AGENT_STOPPED, userId, agent, null, 0, 0, false));
}
public void logManagingTrust(int userId, ComponentName agent, boolean managing) {
addEvent(new Event(TYPE_MANAGING_TRUST, userId, agent, null, 0, 0, managing));
}
public void logDevicePolicyChanged() {
addEvent(new Event(TYPE_POLICY_CHANGED, UserHandle.USER_ALL, null, null, 0, 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
&& ev.userId != UserHandle.USER_ALL) {
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(", ");
}
if (ev.agent != null) {
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, flags=%s",
ev.message, formatDuration(ev.duration), dumpGrantFlags(ev.flags));
break;
case TYPE_MANAGING_TRUST:
writer.printf(", managingTrust=" + ev.managingTrust);
break;
default:
}
writer.println();
count++;
}
}
public 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";
case TYPE_AGENT_CONNECTED:
return "AgentConnected";
case TYPE_AGENT_STOPPED:
return "AgentStopped";
case TYPE_MANAGING_TRUST:
return "ManagingTrust";
case TYPE_POLICY_CHANGED:
return "DevicePolicyChanged";
default:
return "Unknown(" + type + ")";
}
}
private String dumpGrantFlags(int flags) {
StringBuilder sb = new StringBuilder();
if ((flags & TrustAgentService.FLAG_GRANT_TRUST_INITIATED_BY_USER) != 0) {
if (sb.length() != 0) sb.append('|');
sb.append("INITIATED_BY_USER");
}
if ((flags & TrustAgentService.FLAG_GRANT_TRUST_DISMISS_KEYGUARD) != 0) {
if (sb.length() != 0) sb.append('|');
sb.append("DISMISS_KEYGUARD");
}
if (sb.length() == 0) {
sb.append('0');
}
return sb.toString();
}
}