blob: 788ff9b9d5b6630eba819535d269dc47a85592f1 [file] [log] [blame]
/*
* Copyright (C) 2015 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.traceur;
import android.sysprop.TraceProperties;
import android.text.TextUtils;
import android.util.Log;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.List;
import java.util.TreeMap;
import com.android.traceur.TraceUtils.Streamer;
/**
* Utility functions for calling atrace
*/
public class AtraceUtils implements TraceUtils.TraceEngine {
static final String TAG = "Traceur";
private static final String DEBUG_TRACING_FILE = "/sys/kernel/debug/tracing/tracing_on";
private static final String TRACING_FILE = "/sys/kernel/tracing/tracing_on";
public static String NAME = "ATRACE";
private static String OUTPUT_EXTENSION = "ctrace";
public String getName() {
return NAME;
}
public String getOutputExtension() {
return OUTPUT_EXTENSION;
}
/* Note: longTrace and maxLongTrace* parameters are ignored in atrace mode. */
public boolean traceStart(Collection<String> tags, int bufferSizeKb, boolean apps,
boolean longTrace, int maxLongTraceSizeMb, int maxLongTraceDurationMinutes) {
String appParameter = apps ? "-a '*' " : "";
String cmd = "atrace --async_start -c -b " + bufferSizeKb + " "
+ appParameter + TextUtils.join(" ", tags);
Log.v(TAG, "Starting async atrace: " + cmd);
try {
Process atrace = TraceUtils.exec(cmd);
if (atrace.waitFor() != 0) {
Log.e(TAG, "atraceStart failed with: " + atrace.exitValue());
return false;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return true;
}
public void traceStop() {
String cmd = "atrace --async_stop > /dev/null";
Log.v(TAG, "Stopping async atrace: " + cmd);
try {
Process atrace = TraceUtils.exec(cmd);
if (atrace.waitFor() != 0) {
Log.e(TAG, "atraceStop failed with: " + atrace.exitValue());
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public boolean traceDump(File outFile) {
String cmd = "atrace --async_stop -z -c -o " + outFile;
Log.v(TAG, "Dumping async atrace: " + cmd);
try {
Process atrace = TraceUtils.exec(cmd);
if (atrace.waitFor() != 0) {
Log.e(TAG, "atraceDump failed with: " + atrace.exitValue());
return false;
}
Process ps = TraceUtils.exec("ps -AT", null, false);
new Streamer("atraceDump:ps:stdout",
ps.getInputStream(), new FileOutputStream(outFile, true /* append */));
if (ps.waitFor() != 0) {
Log.e(TAG, "atraceDump:ps failed with: " + ps.exitValue());
return false;
}
// Set the new file world readable to allow it to be adb pulled.
outFile.setReadable(true, false); // (readable, ownerOnly)
outFile.setWritable(true, false); // (readable, ownerOnly)
} catch (Exception e) {
throw new RuntimeException(e);
}
return true;
}
public boolean isTracingOn() {
boolean userInitiatedTracingFlag =
TraceProperties.user_initiated().orElse(false);
if (!userInitiatedTracingFlag) {
return false;
}
boolean tracingOnFlag = false;
try {
List<String> tracingOnContents;
Path debugTracingOnPath = Paths.get(DEBUG_TRACING_FILE);
Path tracingOnPath = Paths.get(TRACING_FILE);
if (Files.isReadable(debugTracingOnPath)) {
tracingOnContents = Files.readAllLines(debugTracingOnPath);
} else if (Files.isReadable(tracingOnPath)) {
tracingOnContents = Files.readAllLines(tracingOnPath);
} else {
return false;
}
tracingOnFlag = !tracingOnContents.get(0).equals("0");
} catch (IOException e) {
throw new RuntimeException(e);
}
return userInitiatedTracingFlag && tracingOnFlag;
}
public static TreeMap<String,String> atraceListCategories() {
String cmd = "atrace --list_categories";
Log.v(TAG, "Listing tags: " + cmd);
try {
Process atrace = TraceUtils.exec(cmd, null, false);
BufferedReader stdout = new BufferedReader(
new InputStreamReader(atrace.getInputStream()));
if (atrace.waitFor() != 0) {
Log.e(TAG, "atraceListCategories failed with: " + atrace.exitValue());
}
TreeMap<String, String> result = new TreeMap<>();
String line;
while ((line = stdout.readLine()) != null) {
String[] fields = line.trim().split(" - ", 2);
if (fields.length == 2) {
result.put(fields[0], fields[1]);
}
}
return result;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}