Update app_api to fix style/lint issues
Test: manually invoked/profiled MainActivity
- Added Nullable/NonNull annotations
- Added RequiredAPI annotations
- Switch to consistent mFoo naming
And several other lint suggestions Android Studio suggested.
Additionally, updated target/compile API of demo.
These lint / style issues were found when copying this code into
Jetpack Benchmark, in the AndroidX repository:
https://android-review.googlesource.com/c/platform/frameworks/support/+/1343923
Change-Id: I9fd876f1d15a4812d1ef52958661050b258ca38d
diff --git a/simpleperf/app_api/java/com/android/simpleperf/ProfileSession.java b/simpleperf/app_api/java/com/android/simpleperf/ProfileSession.java
index a3d4796..d1dbc53 100644
--- a/simpleperf/app_api/java/com/android/simpleperf/ProfileSession.java
+++ b/simpleperf/app_api/java/com/android/simpleperf/ProfileSession.java
@@ -19,6 +19,10 @@
import android.os.Build;
import android.system.OsConstants;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.RequiresApi;
+
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
@@ -55,6 +59,7 @@
* process, filter logcat with `simpleperf`.
* </p>
*/
+@RequiresApi(28)
public class ProfileSession {
private static final String SIMPLEPERF_PATH_IN_IMAGE = "/system/bin/simpleperf";
@@ -65,27 +70,27 @@
STOPPED,
}
- private State state = State.NOT_YET_STARTED;
- private String appDataDir;
- private String simpleperfPath;
- private String simpleperfDataDir;
- private Process simpleperfProcess;
- private boolean traceOffcpu = false;
+ private State mState = State.NOT_YET_STARTED;
+ private final String mAppDataDir;
+ private String mSimpleperfPath;
+ private final String mSimpleperfDataDir;
+ private Process mSimpleperfProcess;
+ private boolean mTraceOffCpu = false;
/**
* @param appDataDir the same as android.content.Context.getDataDir().
* ProfileSession stores profiling data in appDataDir/simpleperf_data/.
*/
- public ProfileSession(String appDataDir) {
- this.appDataDir = appDataDir;
- simpleperfDataDir = appDataDir + "/simpleperf_data";
+ public ProfileSession(@NonNull String appDataDir) {
+ mAppDataDir = appDataDir;
+ mSimpleperfDataDir = appDataDir + "/simpleperf_data";
}
/**
* ProfileSession assumes appDataDir as /data/data/app_package_name.
*/
public ProfileSession() {
- String packageName = "";
+ String packageName;
try {
String s = readInputStream(new FileInputStream("/proc/self/cmdline"));
for (int i = 0; i < s.length(); i++) {
@@ -101,15 +106,15 @@
if (packageName.isEmpty()) {
throw new Error("failed to find packageName");
}
- appDataDir = "/data/data/" + packageName;
- simpleperfDataDir = appDataDir + "/simpleperf_data";
+ mAppDataDir = "/data/data/" + packageName;
+ mSimpleperfDataDir = mAppDataDir + "/simpleperf_data";
}
/**
* Start recording.
* @param options RecordOptions
*/
- public void startRecording(RecordOptions options) {
+ public void startRecording(@NonNull RecordOptions options) {
startRecording(options.toRecordArgs());
}
@@ -117,77 +122,77 @@
* Start recording.
* @param args arguments for `simpleperf record` cmd.
*/
- public synchronized void startRecording(List<String> args) {
- if (state != State.NOT_YET_STARTED) {
- throw new AssertionError("startRecording: session in wrong state " + state);
+ public synchronized void startRecording(@NonNull List<String> args) {
+ if (mState != State.NOT_YET_STARTED) {
+ throw new AssertionError("startRecording: session in wrong state " + mState);
}
for (String arg : args) {
if (arg.equals("--trace-offcpu")) {
- traceOffcpu = true;
+ mTraceOffCpu = true;
}
}
- simpleperfPath = findSimpleperf();
+ mSimpleperfPath = findSimpleperf();
checkIfPerfEnabled();
createSimpleperfDataDir();
- createSimpleperfProcess(simpleperfPath, args);
- state = State.STARTED;
+ createSimpleperfProcess(mSimpleperfPath, args);
+ mState = State.STARTED;
}
/**
* Pause recording. No samples are generated in paused state.
*/
public synchronized void pauseRecording() {
- if (state != State.STARTED) {
- throw new AssertionError("pauseRecording: session in wrong state " + state);
+ if (mState != State.STARTED) {
+ throw new AssertionError("pauseRecording: session in wrong state " + mState);
}
- if (traceOffcpu) {
+ if (mTraceOffCpu) {
throw new AssertionError(
"--trace-offcpu option doesn't work well with pause/resume recording");
}
sendCmd("pause");
- state = State.PAUSED;
+ mState = State.PAUSED;
}
/**
* Resume a paused session.
*/
public synchronized void resumeRecording() {
- if (state != State.PAUSED) {
- throw new AssertionError("resumeRecording: session in wrong state " + state);
+ if (mState != State.PAUSED) {
+ throw new AssertionError("resumeRecording: session in wrong state " + mState);
}
sendCmd("resume");
- state = State.STARTED;
+ mState = State.STARTED;
}
/**
* Stop recording and generate a recording file under appDataDir/simpleperf_data/.
*/
public synchronized void stopRecording() {
- if (state != State.STARTED && state != State.PAUSED) {
- throw new AssertionError("stopRecording: session in wrong state " + state);
+ if (mState != State.STARTED && mState != State.PAUSED) {
+ throw new AssertionError("stopRecording: session in wrong state " + mState);
}
- if (Build.VERSION.SDK_INT == Build.VERSION_CODES.P + 1 &&
- simpleperfPath.equals(SIMPLEPERF_PATH_IN_IMAGE)) {
+ if (Build.VERSION.SDK_INT == Build.VERSION_CODES.P + 1
+ && mSimpleperfPath.equals(SIMPLEPERF_PATH_IN_IMAGE)) {
// The simpleperf shipped on Android Q contains a bug, which may make it abort if
// calling simpleperfProcess.destroy().
destroySimpleperfProcessWithoutClosingStdin();
} else {
- simpleperfProcess.destroy();
+ mSimpleperfProcess.destroy();
}
try {
- int exitCode = simpleperfProcess.waitFor();
+ int exitCode = mSimpleperfProcess.waitFor();
if (exitCode != 0) {
throw new AssertionError("simpleperf exited with error: " + exitCode);
}
} catch (InterruptedException e) {
}
- simpleperfProcess = null;
- state = State.STOPPED;
+ mSimpleperfProcess = null;
+ mState = State.STOPPED;
}
private void destroySimpleperfProcessWithoutClosingStdin() {
// In format "Process[pid=? ..."
- String s = simpleperfProcess.toString();
+ String s = mSimpleperfProcess.toString();
final String prefix = "Process[pid=";
if (s.startsWith(prefix)) {
int startIndex = prefix.length();
@@ -198,7 +203,7 @@
return;
}
}
- simpleperfProcess.destroy();
+ mSimpleperfProcess.destroy();
}
private String readInputStream(InputStream in) {
@@ -225,19 +230,20 @@
throw new Error("can't find simpleperf on device. Please run api_profiler.py.");
}
- private boolean isExecutableFile(String path) {
+ private boolean isExecutableFile(@NonNull String path) {
File file = new File(path);
return file.canExecute();
}
+ @Nullable
private String findSimpleperfInTempDir() {
String path = "/data/local/tmp/simpleperf";
File file = new File(path);
- if (!file.isFile()){
+ if (!file.isFile()) {
return null;
}
// Copy it to app dir to execute it.
- String toPath = appDataDir + "/simpleperf";
+ String toPath = mAppDataDir + "/simpleperf";
try {
Process process = new ProcessBuilder()
.command("cp", path, toPath).start();
@@ -255,7 +261,7 @@
Process process = new ProcessBuilder().command(toPath, "list", "sw").start();
process.waitFor();
String data = readInputStream(process.getInputStream());
- if (data.indexOf("cpu-clock") == -1) {
+ if (!data.contains("cpu-clock")) {
return null;
}
} catch (Exception e) {
@@ -265,7 +271,7 @@
}
private void checkIfPerfEnabled() {
- String value = "";
+ String value;
Process process;
try {
process = new ProcessBuilder()
@@ -280,13 +286,13 @@
}
value = readInputStream(process.getInputStream());
if (value.startsWith("1")) {
- throw new Error("linux perf events aren't enabled on the device." +
- " Please run api_profiler.py.");
+ throw new Error("linux perf events aren't enabled on the device."
+ + " Please run api_profiler.py.");
}
}
private void createSimpleperfDataDir() {
- File file = new File(simpleperfDataDir);
+ File file = new File(mSimpleperfDataDir);
if (!file.isDirectory()) {
file.mkdir();
}
@@ -307,9 +313,9 @@
args.addAll(recordArgs);
// 2. Create the simpleperf process.
- ProcessBuilder pb = new ProcessBuilder(args).directory(new File(simpleperfDataDir));
+ ProcessBuilder pb = new ProcessBuilder(args).directory(new File(mSimpleperfDataDir));
try {
- simpleperfProcess = pb.start();
+ mSimpleperfProcess = pb.start();
} catch (IOException e) {
throw new Error("failed to create simpleperf process: " + e.getMessage());
}
@@ -321,11 +327,11 @@
}
}
- private void sendCmd(String cmd) {
+ private void sendCmd(@NonNull String cmd) {
cmd += "\n";
try {
- simpleperfProcess.getOutputStream().write(cmd.getBytes());
- simpleperfProcess.getOutputStream().flush();
+ mSimpleperfProcess.getOutputStream().write(cmd.getBytes());
+ mSimpleperfProcess.getOutputStream().flush();
} catch (IOException e) {
throw new Error("failed to send cmd to simpleperf: " + e.getMessage());
}
@@ -334,6 +340,7 @@
}
}
+ @NonNull
private String readReply() {
// Read one byte at a time to stop at line break or EOF. BufferedReader will try to read
// more than available and make us blocking, so don't use it.
@@ -341,13 +348,13 @@
while (true) {
int c = -1;
try {
- c = simpleperfProcess.getInputStream().read();
+ c = mSimpleperfProcess.getInputStream().read();
} catch (IOException e) {
}
if (c == -1 || c == '\n') {
break;
}
- s += (char)c;
+ s += (char) c;
}
return s;
}
diff --git a/simpleperf/app_api/java/com/android/simpleperf/RecordOptions.java b/simpleperf/app_api/java/com/android/simpleperf/RecordOptions.java
index 3ed39fb..ae65b94 100644
--- a/simpleperf/app_api/java/com/android/simpleperf/RecordOptions.java
+++ b/simpleperf/app_api/java/com/android/simpleperf/RecordOptions.java
@@ -18,6 +18,10 @@
import android.system.Os;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.RequiresApi;
+
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
@@ -39,30 +43,34 @@
* session.startRecording(options);
* </p>
*/
+@RequiresApi(28)
public class RecordOptions {
/**
* Set output filename. Default is perf-<month>-<day>-<hour>-<minute>-<second>.data.
* The file will be generated under simpleperf_data/.
*/
- public RecordOptions setOutputFilename(String filename) {
- outputFilename = filename;
+ @NonNull
+ public RecordOptions setOutputFilename(@NonNull String filename) {
+ mOutputFilename = filename;
return this;
}
/**
* Set event to record. Default is cpu-cycles. See `simpleperf list` for all available events.
*/
- public RecordOptions setEvent(String event) {
- this.event = event;
+ @NonNull
+ public RecordOptions setEvent(@NonNull String event) {
+ mEvent = event;
return this;
}
/**
* Set how many samples to generate each second running. Default is 4000.
*/
+ @NonNull
public RecordOptions setSampleFrequency(int freq) {
- this.freq = freq;
+ mFreq = freq;
return this;
}
@@ -70,86 +78,92 @@
* Set record duration. The record stops after `durationInSecond` seconds. By default,
* record stops only when stopRecording() is called.
*/
+ @NonNull
public RecordOptions setDuration(double durationInSecond) {
- this.durationInSecond = durationInSecond;
+ mDurationInSeconds = durationInSecond;
return this;
}
/**
* Record some threads in the app process. By default, record all threads in the process.
*/
- public RecordOptions setSampleThreads(List<Integer> threads) {
- this.threads.addAll(threads);
+ @NonNull
+ public RecordOptions setSampleThreads(@NonNull List<Integer> threads) {
+ mThreads.addAll(threads);
return this;
}
/**
* Record dwarf based call graph. It is needed to get Java callstacks.
*/
+ @NonNull
public RecordOptions recordDwarfCallGraph() {
- this.dwarfCallGraph = true;
- this.fpCallGraph = false;
+ mDwarfCallGraph = true;
+ mFpCallGraph = false;
return this;
}
/**
* Record frame pointer based call graph. It is suitable to get C++ callstacks on 64bit devices.
*/
+ @NonNull
public RecordOptions recordFramePointerCallGraph() {
- this.fpCallGraph = true;
- this.dwarfCallGraph = false;
+ mFpCallGraph = true;
+ mDwarfCallGraph = false;
return this;
}
/**
* Trace context switch info to show where threads spend time off cpu.
*/
+ @NonNull
public RecordOptions traceOffCpu() {
- this.traceOffCpu = true;
+ mTraceOffCpu = true;
return this;
}
/**
* Translate record options into arguments for `simpleperf record` cmd.
*/
+ @NonNull
public List<String> toRecordArgs() {
ArrayList<String> args = new ArrayList<>();
- String filename = outputFilename;
+ String filename = mOutputFilename;
if (filename == null) {
filename = getDefaultOutputFilename();
}
args.add("-o");
args.add(filename);
args.add("-e");
- args.add(event);
+ args.add(mEvent);
args.add("-f");
- args.add(String.valueOf(freq));
- if (durationInSecond != 0.0) {
+ args.add(String.valueOf(mFreq));
+ if (mDurationInSeconds != 0.0) {
args.add("--duration");
- args.add(String.valueOf(durationInSecond));
+ args.add(String.valueOf(mDurationInSeconds));
}
- if (threads.isEmpty()) {
+ if (mThreads.isEmpty()) {
args.add("-p");
args.add(String.valueOf(Os.getpid()));
} else {
String s = "";
- for (int i = 0; i < threads.size(); i++) {
+ for (int i = 0; i < mThreads.size(); i++) {
if (i > 0) {
s += ",";
}
- s += threads.get(i).toString();
+ s += mThreads.get(i).toString();
}
args.add("-t");
args.add(s);
}
- if (dwarfCallGraph) {
+ if (mDwarfCallGraph) {
args.add("-g");
- } else if (fpCallGraph) {
+ } else if (mFpCallGraph) {
args.add("--call-graph");
args.add("fp");
}
- if (traceOffCpu) {
+ if (mTraceOffCpu) {
args.add("--trace-offcpu");
}
return args;
@@ -161,12 +175,22 @@
return time.format(formatter);
}
- private String outputFilename;
- private String event = "cpu-cycles";
- private int freq = 4000;
- private double durationInSecond = 0.0;
- private ArrayList<Integer> threads = new ArrayList<>();
- private boolean dwarfCallGraph = false;
- private boolean fpCallGraph = false;
- private boolean traceOffCpu = false;
+ @Nullable
+ private String mOutputFilename;
+
+ @NonNull
+ private String mEvent = "cpu-cycles";
+
+ private int mFreq = 4000;
+
+ private double mDurationInSeconds = 0.0;
+
+ @NonNull
+ private ArrayList<Integer> mThreads = new ArrayList<>();
+
+ private boolean mDwarfCallGraph = false;
+
+ private boolean mFpCallGraph = false;
+
+ private boolean mTraceOffCpu = false;
}
diff --git a/simpleperf/demo/JavaApi/app/build.gradle b/simpleperf/demo/JavaApi/app/build.gradle
index be32645..e53f7da 100644
--- a/simpleperf/demo/JavaApi/app/build.gradle
+++ b/simpleperf/demo/JavaApi/app/build.gradle
@@ -1,13 +1,13 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 28
+ compileSdkVersion 29
defaultConfig {
applicationId "simpleperf.demo.java_api"
// Simpleperf profiles interpreted/jitted Java code on Android >= P.
// https://android.googlesource.com/platform/system/extras/+/master/simpleperf/doc/README.md#prepare-an-android-application
minSdkVersion 28
- targetSdkVersion 28
+ targetSdkVersion 29
versionCode 1
versionName "1.0"
}