Home | History | Annotate | Download | only in walt
      1 /*
      2  * Copyright (C) 2017 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 org.chromium.latency.walt;
     18 
     19 import android.content.Context;
     20 import android.os.Environment;
     21 
     22 import java.io.File;
     23 import java.io.FileOutputStream;
     24 import java.io.IOException;
     25 import java.io.OutputStreamWriter;
     26 import java.text.DecimalFormat;
     27 import java.util.ArrayList;
     28 
     29 /**
     30  * Used to log events for Android systrace
     31  */
     32 class TraceLogger {
     33 
     34     private static final Object LOCK = new Object();
     35     private static TraceLogger instance;
     36 
     37     private ArrayList<TraceEvent> traceEvents;
     38 
     39     public static TraceLogger getInstance() {
     40         synchronized (LOCK) {
     41             if (instance == null) {
     42                 instance = new TraceLogger();
     43             }
     44             return instance;
     45         }
     46     }
     47 
     48     private TraceLogger() {
     49         traceEvents = new ArrayList<>();
     50     }
     51 
     52     public synchronized void log(long startTimeMicros, long finishTimeMicros, String title, String description) {
     53         traceEvents.add(new TraceEvent(startTimeMicros, finishTimeMicros, title, description));
     54     }
     55 
     56     public String getLogText() {
     57         DecimalFormat df = new DecimalFormat(".000000");
     58         StringBuilder sb = new StringBuilder();
     59         int pid = android.os.Process.myPid();
     60         for (TraceEvent e : traceEvents) {
     61             sb.append(String.format(
     62                     "WALTThread-1234 (%d) [000] ...1 %s: tracing_mark_write: B|%d|%s|description=%s|WALT\n",
     63                     pid, df.format(e.startTimeMicros / 1e6), pid, e.title, e.description));
     64             sb.append(String.format(
     65                     "WALTThread-1234 (%d) [000] ...1 %s: tracing_mark_write: E|%d|%s||WALT\n",
     66                     pid, df.format(e.finishTimeMicros / 1e6), pid, e.title));
     67         }
     68         return sb.toString();
     69     }
     70 
     71     void flush(Context context) {
     72         SimpleLogger logger = SimpleLogger.getInstance(context);
     73         if (!isExternalStorageWritable()) {
     74             logger.log("ERROR: could not write systrace logs to file");
     75             return;
     76         }
     77         writeSystraceLogs(context);
     78         traceEvents.clear();
     79     }
     80 
     81     private void writeSystraceLogs(Context context) {
     82         File file = new File(context.getExternalFilesDir(null), "trace.txt");
     83         SimpleLogger logger = SimpleLogger.getInstance(context);
     84         try {
     85             OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file, true));
     86             writer.write(getLogText());
     87             writer.close();
     88             logger.log(String.format("TraceLogger wrote %d events to %s",
     89                     traceEvents.size(), file.getAbsolutePath()));
     90         } catch (IOException e) {
     91             logger.log("ERROR: IOException writing to trace.txt");
     92             e.printStackTrace();
     93         }
     94     }
     95 
     96     private boolean isExternalStorageWritable() {
     97         String state = Environment.getExternalStorageState();
     98         return Environment.MEDIA_MOUNTED.equals(state);
     99     }
    100 
    101     private class TraceEvent {
    102         long startTimeMicros;
    103         long finishTimeMicros;
    104         String title;
    105         String description;
    106         TraceEvent(long startTimeMicros, long finishTimeMicros, String title, String description) {
    107             this.startTimeMicros = startTimeMicros;
    108             this.finishTimeMicros = finishTimeMicros;
    109             this.title = title;
    110             this.description = description;
    111         }
    112     }
    113 }
    114