blob: 2548edc237f03cd8848695c8898b9d14e23f6801 [file] [log] [blame]
/*
* Copyright (C) 2012 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.ide.eclipse.ddms.systrace;
import com.google.common.base.Charsets;
import com.google.common.io.Files;
import java.io.File;
import java.io.IOException;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
/** {@link SystraceOutputParser} receives the output of atrace command run on the device,
* parses it and generates html based on the trace */
public class SystraceOutputParser {
private static final String TRACE_START = "TRACE:\n"; //$NON-NLS-1$
private final boolean mUncompress;
private final String mJs;
private final String mCss;
private final String mHtmlPrefix;
private final String mHtmlSuffix;
private byte[] mAtraceOutput;
private int mAtraceLength;
private int mSystraceIndex = -1;
/**
* Constructs a atrace output parser.
* @param compressedStream Is the input stream compressed using zlib?
* @param systraceJs systrace javascript content
* @param systraceCss systrace css content
*/
public SystraceOutputParser(boolean compressedStream, String systraceJs, String systraceCss,
String htmlPrefix, String htmlSuffix) {
mUncompress = compressedStream;
mJs = systraceJs;
mCss = systraceCss;
mHtmlPrefix = htmlPrefix;
mHtmlSuffix = htmlSuffix;
}
/**
* Parses the atrace output for systrace content.
* @param atraceOutput output bytes from atrace
*/
public void parse(byte[] atraceOutput) {
mAtraceOutput = atraceOutput;
mAtraceLength = atraceOutput.length;
removeCrLf();
// locate the trace start marker within the first hundred bytes
String header = new String(mAtraceOutput, 0, Math.min(100, mAtraceLength));
mSystraceIndex = locateSystraceData(header);
if (mSystraceIndex < 0) {
throw new RuntimeException("Unable to find trace start marker 'TRACE:':\n" + header);
}
}
/** Replaces \r\n with \n in {@link #mAtraceOutput}. */
private void removeCrLf() {
int dst = 0;
for (int src = 0; src < mAtraceLength - 1; src++, dst++) {
byte copy;
if (mAtraceOutput[src] == '\r' && mAtraceOutput[src + 1] == '\n') {
copy = '\n';
src++;
} else {
copy = mAtraceOutput[src];
}
mAtraceOutput[dst] = copy;
}
mAtraceLength = dst;
}
private int locateSystraceData(String header) {
int index = header.indexOf(TRACE_START);
if (index < 0) {
return -1;
} else {
return index + TRACE_START.length();
}
}
public String getSystraceHtml() {
if (mSystraceIndex < 0) {
return "";
}
String trace = "";
if (mUncompress) {
Inflater decompressor = new Inflater();
decompressor.setInput(mAtraceOutput, mSystraceIndex, mAtraceLength - mSystraceIndex);
byte[] buf = new byte[4096];
int n;
StringBuilder sb = new StringBuilder(1000);
try {
while ((n = decompressor.inflate(buf)) > 0) {
sb.append(new String(buf, 0, n));
}
} catch (DataFormatException e) {
throw new RuntimeException(e);
}
decompressor.end();
trace = sb.toString();
} else {
trace = new String(mAtraceOutput, mSystraceIndex, mAtraceLength - mSystraceIndex);
}
// each line should end with the characters \n\ followed by a newline
String html_out = trace.replaceAll("\n", "\\\\n\\\\\n");
String header = String.format(mHtmlPrefix, mCss, mJs, "");
String footer = mHtmlSuffix;
return header + html_out + footer;
}
public static String getJs(File assetsFolder) {
try {
return String.format("<script language=\"javascript\">%s</script>",
Files.toString(new File(assetsFolder, "script.js"), Charsets.UTF_8));
} catch (IOException e) {
return "";
}
}
public static String getCss(File assetsFolder) {
try {
return String.format("<style type=\"text/css\">%s</style>",
Files.toString(new File(assetsFolder, "style.css"), Charsets.UTF_8));
} catch (IOException e) {
return "";
}
}
public static String getHtmlPrefix(File assetsFolder) {
return getHtmlTemplate(assetsFolder, "prefix.html");
}
public static String getHtmlSuffix(File assetsFolder) {
return getHtmlTemplate(assetsFolder, "suffix.html");
}
private static String getHtmlTemplate(File assetsFolder, String htmlFileName) {
try {
return Files.toString(new File(assetsFolder, htmlFileName), Charsets.UTF_8);
} catch (IOException e) {
return "";
}
}
}