diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/systrace/SystraceOutputParser.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/systrace/SystraceOutputParser.java | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/systrace/SystraceOutputParser.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/systrace/SystraceOutputParser.java new file mode 100644 index 000000000..2548edc23 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/systrace/SystraceOutputParser.java @@ -0,0 +1,169 @@ +/* + * 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 ""; + } + } +} |