Home | History | Annotate | Download | only in systrace
      1 /*
      2  * Copyright (C) 2012 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 
     17 package com.android.ide.eclipse.ddms.systrace;
     18 
     19 import com.google.common.base.Charsets;
     20 import com.google.common.io.Files;
     21 
     22 import java.io.File;
     23 import java.io.IOException;
     24 import java.util.zip.DataFormatException;
     25 import java.util.zip.Inflater;
     26 
     27 /** {@link SystraceOutputParser} receives the output of atrace command run on the device,
     28  * parses it and generates html based on the trace */
     29 public class SystraceOutputParser {
     30     private static final String TRACE_START = "TRACE:\n"; //$NON-NLS-1$
     31 
     32     private final boolean mUncompress;
     33     private final String mJs;
     34     private final String mCss;
     35     private final String mHtmlPrefix;
     36     private final String mHtmlSuffix;
     37 
     38     private byte[] mAtraceOutput;
     39     private int mAtraceLength;
     40     private int mSystraceIndex = -1;
     41 
     42     /**
     43      * Constructs a atrace output parser.
     44      * @param compressedStream Is the input stream compressed using zlib?
     45      * @param systraceJs systrace javascript content
     46      * @param systraceCss systrace css content
     47      */
     48     public SystraceOutputParser(boolean compressedStream, String systraceJs, String systraceCss,
     49             String htmlPrefix, String htmlSuffix) {
     50         mUncompress = compressedStream;
     51         mJs = systraceJs;
     52         mCss = systraceCss;
     53         mHtmlPrefix = htmlPrefix;
     54         mHtmlSuffix = htmlSuffix;
     55     }
     56 
     57     /**
     58      * Parses the atrace output for systrace content.
     59      * @param atraceOutput output bytes from atrace
     60      */
     61     public void parse(byte[] atraceOutput) {
     62         mAtraceOutput = atraceOutput;
     63         mAtraceLength = atraceOutput.length;
     64 
     65         removeCrLf();
     66 
     67         // locate the trace start marker within the first hundred bytes
     68         String header = new String(mAtraceOutput, 0, Math.min(100, mAtraceLength));
     69         mSystraceIndex = locateSystraceData(header);
     70 
     71         if (mSystraceIndex < 0) {
     72             throw new RuntimeException("Unable to find trace start marker 'TRACE:':\n" + header);
     73         }
     74     }
     75 
     76     /** Replaces \r\n with \n in {@link #mAtraceOutput}. */
     77     private void removeCrLf() {
     78         int dst = 0;
     79         for (int src = 0; src < mAtraceLength - 1; src++, dst++) {
     80             byte copy;
     81             if (mAtraceOutput[src] == '\r' && mAtraceOutput[src + 1] == '\n') {
     82                 copy = '\n';
     83                 src++;
     84             } else {
     85                 copy = mAtraceOutput[src];
     86             }
     87             mAtraceOutput[dst] = copy;
     88         }
     89 
     90         mAtraceLength = dst;
     91     }
     92 
     93     private int locateSystraceData(String header) {
     94         int index = header.indexOf(TRACE_START);
     95         if (index < 0) {
     96             return -1;
     97         } else {
     98             return index + TRACE_START.length();
     99         }
    100     }
    101 
    102     public String getSystraceHtml() {
    103         if (mSystraceIndex < 0) {
    104             return "";
    105         }
    106 
    107         String trace = "";
    108         if (mUncompress) {
    109             Inflater decompressor = new Inflater();
    110             decompressor.setInput(mAtraceOutput, mSystraceIndex, mAtraceLength - mSystraceIndex);
    111 
    112             byte[] buf = new byte[4096];
    113             int n;
    114             StringBuilder sb = new StringBuilder(1000);
    115             try {
    116                 while ((n = decompressor.inflate(buf)) > 0) {
    117                     sb.append(new String(buf, 0, n));
    118                 }
    119             } catch (DataFormatException e) {
    120                 throw new RuntimeException(e);
    121             }
    122             decompressor.end();
    123 
    124             trace = sb.toString();
    125         } else {
    126             trace = new String(mAtraceOutput, mSystraceIndex, mAtraceLength - mSystraceIndex);
    127         }
    128 
    129         // each line should end with the characters \n\ followed by a newline
    130         String html_out = trace.replaceAll("\n", "\\\\n\\\\\n");
    131         String header = String.format(mHtmlPrefix, mCss, mJs, "");
    132         String footer = mHtmlSuffix;
    133         return header + html_out + footer;
    134     }
    135 
    136     public static String getJs(File assetsFolder) {
    137         try {
    138             return String.format("<script language=\"javascript\">%s</script>",
    139                     Files.toString(new File(assetsFolder, "script.js"), Charsets.UTF_8));
    140         } catch (IOException e) {
    141             return "";
    142         }
    143     }
    144 
    145     public static String getCss(File assetsFolder) {
    146         try {
    147             return String.format("<style type=\"text/css\">%s</style>",
    148                     Files.toString(new File(assetsFolder, "style.css"), Charsets.UTF_8));
    149         } catch (IOException e) {
    150             return "";
    151         }
    152     }
    153 
    154     public static String getHtmlPrefix(File assetsFolder) {
    155         return getHtmlTemplate(assetsFolder, "prefix.html");
    156     }
    157 
    158     public static String getHtmlSuffix(File assetsFolder) {
    159         return getHtmlTemplate(assetsFolder, "suffix.html");
    160     }
    161 
    162     private static String getHtmlTemplate(File assetsFolder, String htmlFileName) {
    163         try {
    164             return Files.toString(new File(assetsFolder, htmlFileName), Charsets.UTF_8);
    165         } catch (IOException e) {
    166             return "";
    167         }
    168     }
    169 }
    170