Methods Summary |
---|
private void | addLaunchTime(java.lang.String name, java.lang.Long value)
ArrayList<Long> list = mLaunchMap.get(name);
if (list == null) {
list = new ArrayList<Long>();
mLaunchMap.put(name, list);
}
list.add(value);
|
private void | analyzeData()Analyze the data and writes it to {@link #mOutputFile}
BufferedWriter writer = null;
try {
// make sure the file name has the proper extension.
if (mOutputFile.toLowerCase().endsWith(CVS_EXT) == false) {
mOutputFile = mOutputFile + CVS_EXT;
}
writer = new BufferedWriter(new FileWriter(mOutputFile));
StringBuilder builder = new StringBuilder();
// write the list of launch start. One column per activity.
Set<String> activities = mLaunchMap.keySet();
// write the column headers.
for (String activity : activities) {
builder.append(activity).append(DATA_SEPARATOR);
}
writer.write(builder.append('\n").toString());
// loop on the activities and write their values.
boolean moreValues = true;
int index = 0;
while (moreValues) {
moreValues = false;
builder.setLength(0);
for (String activity : activities) {
// get the activity list.
ArrayList<Long> list = mLaunchMap.get(activity);
if (index < list.size()) {
moreValues = true;
builder.append(list.get(index).longValue()).append(DATA_SEPARATOR);
} else {
builder.append(DATA_SEPARATOR);
}
}
// write the line.
if (moreValues) {
writer.write(builder.append('\n").toString());
}
index++;
}
// write per-activity stats.
for (String activity : activities) {
builder.setLength(0);
builder.append(activity).append(DATA_SEPARATOR);
// get the activity list.
ArrayList<Long> list = mLaunchMap.get(activity);
// sort the list
Collections.sort(list);
// write min/max
builder.append(list.get(0).longValue()).append(DATA_SEPARATOR);
builder.append(list.get(list.size()-1).longValue()).append(DATA_SEPARATOR);
// write median value
builder.append(list.get(list.size()/2).longValue()).append(DATA_SEPARATOR);
// compute and write average
long total = 0; // despite being encoded on a long, the values are low enough that
// a Long should be enough to compute the total
for (Long value : list) {
total += value.longValue();
}
builder.append(total / list.size()).append(DATA_SEPARATOR);
// finally write the data.
writer.write(builder.append('\n").toString());
}
} finally {
writer.close();
}
|
private void | checkInputValidity(java.lang.String option)
if (mInputTextFile != null || mInputBinaryFile != null) {
printAndExit(String.format("ERROR: %1$s cannot be used with an input file.", option),
false /* terminate */);
} else if (mInputFolder != null) {
printAndExit(String.format("ERROR: %1$s cannot be used with an input file.", option),
false /* terminate */);
} else if (mInputDevice != null) {
printAndExit(String.format("ERROR: %1$s cannot be used with an input device serial number.",
option), false /* terminate */);
}
|
private void | grabLogFrom(com.android.ddmlib.Device device)
mParser = new EventLogParser();
if (mParser.init(device) == false) {
printAndExit("Failed to get event-log-tags from " + device.getSerialNumber(),
true /* terminate*/);
}
LogReceiver receiver = new LogReceiver(this);
device.runEventLogService(receiver);
|
public static void | main(java.lang.String[] args)
new EventAnalyzer().run(args);
|
public void | newData(byte[] data, int offset, int length)
// we ignore raw data. New entries are processed in #newEntry(LogEntry)
|
public void | newEntry(com.android.ddmlib.log.LogReceiver.LogEntry entry)
// parse and process the entry data.
processEvent(mParser.parse(entry));
|
private void | parseBinaryLogFile()Parses a binary event log file located at {@link #mInputBinaryFile}.
mParser = new EventLogParser();
String tagFile = mInputBinaryFile + TAG_FILE_EXT;
if (mParser.init(tagFile) == false) {
// if we have an alternate location
if (mAlternateTagFile != null) {
if (mParser.init(mAlternateTagFile) == false) {
printAndExit("Failed to get event tags from " + mAlternateTagFile,
false /* terminate*/);
}
} else {
printAndExit("Failed to get event tags from " + tagFile, false /* terminate*/);
}
}
LogReceiver receiver = new LogReceiver(this);
byte[] buffer = new byte[256];
FileInputStream fis = new FileInputStream(mInputBinaryFile);
int count;
while ((count = fis.read(buffer)) != -1) {
receiver.parseNewData(buffer, 0, count);
}
|
private void | parseFolder(java.lang.String folderPath)Parses the log files located in the folder, and its sub-folders.
File f = new File(folderPath);
if (f.isDirectory() == false) {
printAndExit(String.format("%1$s is not a valid folder", folderPath),
false /* terminate */);
}
String[] files = f.list(new FilenameFilter() {
public boolean accept(File dir, String name) {
name = name.toLowerCase();
return name.endsWith(".tag") == false;
}
});
for (String file : files) {
try {
f = new File(folderPath + File.separator + file);
if (f.isDirectory()) {
parseFolder(f.getAbsolutePath());
} else {
parseTextLogFile(f.getAbsolutePath());
}
} catch (IOException e) {
// ignore this file.
}
}
|
private void | parseLogFromDevice()
// init the lib
AndroidDebugBridge.init(false /* debugger support */);
try {
AndroidDebugBridge bridge = AndroidDebugBridge.createBridge();
// we can't just ask for the device list right away, as the internal thread getting
// them from ADB may not be done getting the first list.
// Since we don't really want getDevices() to be blocking, we wait here manually.
int count = 0;
while (bridge.hasInitialDeviceList() == false) {
try {
Thread.sleep(100);
count++;
} catch (InterruptedException e) {
// pass
}
// let's not wait > 10 sec.
if (count > 100) {
printAndExit("Timeout getting device list!", true /* terminate*/);
}
}
// now get the devices
Device[] devices = bridge.getDevices();
for (Device device : devices) {
if (device.getSerialNumber().equals(mInputDevice)) {
grabLogFrom(device);
return;
}
}
System.err.println("Could not find " + mInputDevice);
} finally {
AndroidDebugBridge.terminate();
}
|
private void | parseTextLogFile(java.lang.String filePath)Parse a text Log file.
mParser = new EventLogParser();
String tagFile = filePath + TAG_FILE_EXT;
if (mParser.init(tagFile) == false) {
// if we have an alternate location
if (mAlternateTagFile != null) {
if (mParser.init(mAlternateTagFile) == false) {
printAndExit("Failed to get event tags from " + mAlternateTagFile,
false /* terminate*/);
}
} else {
printAndExit("Failed to get event tags from " + tagFile, false /* terminate*/);
}
}
// read the lines from the file and process them.
BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(filePath)));
String line;
while ((line = reader.readLine()) != null) {
processEvent(mParser.parse(line));
}
|
private static void | printAndExit(java.lang.String message, boolean terminate)
System.out.println(message);
if (terminate) {
AndroidDebugBridge.terminate();
}
System.exit(1);
|
private static void | printUsageAndQuit()
// 80 cols marker: 01234567890123456789012345678901234567890123456789012345678901234567890123456789
System.out.println("Usage:");
System.out.println(" eventanalyzer [-t <TAG_FILE>] <SOURCE> <OUTPUT>");
System.out.println("");
System.out.println("Possible sources:");
System.out.println(" -fb <file> The path to a binary event log, gathered by dumpeventlog");
System.out.println(" -ft <file> The path to a text event log, gathered by adb logcat -b events");
System.out.println(" -F <folder> The path to a folder containing multiple text log files.");
System.out.println(" -s <serial> The serial number of the Device to grab the event log from.");
System.out.println("Options:");
System.out.println(" -t <file> The path to tag file to use in case the one associated with");
System.out.println(" the source is missing");
System.exit(1);
|
private void | processEvent(com.android.ddmlib.log.EventContainer event)
if (event != null && event.mTag == TAG_ACTIVITY_LAUNCH_TIME) {
// get the activity name
try {
String name = event.getValueAsString(0);
// get the launch time
Object value = event.getValue(1);
if (value instanceof Long) {
addLaunchTime(name, (Long)value);
}
} catch (InvalidTypeException e) {
// Couldn't get the name as a string...
// Ignore this event.
}
}
|
private void | run(java.lang.String[] args)
if (args.length == 0) {
printUsageAndQuit();
}
int index = 0;
do {
String argument = args[index++];
if ("-s".equals(argument)) {
checkInputValidity("-s");
if (index == args.length) {
printUsageAndQuit();
}
mInputDevice = args[index++];
} else if ("-fb".equals(argument)) {
checkInputValidity("-fb");
if (index == args.length) {
printUsageAndQuit();
}
mInputBinaryFile = args[index++];
} else if ("-ft".equals(argument)) {
checkInputValidity("-ft");
if (index == args.length) {
printUsageAndQuit();
}
mInputTextFile = args[index++];
} else if ("-F".equals(argument)) {
checkInputValidity("-F");
if (index == args.length) {
printUsageAndQuit();
}
mInputFolder = args[index++];
} else if ("-t".equals(argument)) {
if (index == args.length) {
printUsageAndQuit();
}
mAlternateTagFile = args[index++];
} else {
// get the filepath and break.
mOutputFile = argument;
// should not be any other device.
if (index < args.length) {
printAndExit("Too many arguments!", false /* terminate */);
}
}
} while (index < args.length);
if ((mInputTextFile == null && mInputBinaryFile == null && mInputFolder == null &&
mInputDevice == null)) {
printUsageAndQuit();
}
File outputParent = new File(mOutputFile).getParentFile();
if (outputParent == null || outputParent.isDirectory() == false) {
printAndExit(String.format("%1$s is not a valid ouput file", mOutputFile),
false /* terminate */);
}
// redirect the log output to /dev/null
Log.setLogOutput(new ILogOutput() {
public void printAndPromptLog(LogLevel logLevel, String tag, String message) {
// pass
}
public void printLog(LogLevel logLevel, String tag, String message) {
// pass
}
});
try {
if (mInputBinaryFile != null) {
parseBinaryLogFile();
} else if (mInputTextFile != null) {
parseTextLogFile(mInputTextFile);
} else if (mInputFolder != null) {
parseFolder(mInputFolder);
} else if (mInputDevice != null) {
parseLogFromDevice();
}
// analyze the data gathered by the parser methods
analyzeData();
} catch (IOException e) {
e.printStackTrace();
}
|