Merge "<stdbool.h> not necessary in C++."
diff --git a/simpleperf/cmd_list.cpp b/simpleperf/cmd_list.cpp
index 7199814..3b22bde 100644
--- a/simpleperf/cmd_list.cpp
+++ b/simpleperf/cmd_list.cpp
@@ -165,6 +165,9 @@
if (IsDumpingRegsForTracepointEventsSupported()) {
printf("trace-offcpu\n");
}
+ if (IsSettingClockIdSupported()) {
+ printf("set-clockid\n");
+ }
}
void RegisterListCommand() {
diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp
index 2bd0506..d83b210 100644
--- a/simpleperf/cmd_record.cpp
+++ b/simpleperf/cmd_record.cpp
@@ -62,6 +62,13 @@
{"ind_call", PERF_SAMPLE_BRANCH_IND_CALL},
};
+static std::unordered_map<std::string, int> clockid_map = {
+ {"realtime", CLOCK_REALTIME},
+ {"monotonic", CLOCK_MONOTONIC},
+ {"monotonic_raw", CLOCK_MONOTONIC_RAW},
+ {"boottime", CLOCK_BOOTTIME},
+};
+
// The max size of records dumped by kernel is 65535, and dump stack size
// should be a multiply of 8, so MAX_DUMP_STACK_SIZE is 65528.
constexpr uint32_t MAX_DUMP_STACK_SIZE = 65528;
@@ -122,6 +129,9 @@
" frame as the method to parse call graph in stack.\n"
" Default is dwarf,65528.\n"
"-g Same as '--call-graph dwarf'.\n"
+"--clockid clock_id Generate timestamps of samples using selected clock.\n"
+" Possible values are: realtime, monotonic,\n"
+" monotonic_raw, boottime, perf. Default is perf.\n"
"--cpu cpu_item1,cpu_item2,...\n"
" Collect samples only on the selected cpus. cpu_item can be cpu\n"
" number like 1, or cpu range like 0-3.\n"
@@ -183,6 +193,7 @@
duration_in_sec_(0),
can_dump_kernel_symbols_(true),
dump_symbols_(true),
+ clockid_("perf"),
event_selection_set_(false),
mmap_page_range_(std::make_pair(1, DESIRED_PAGES_IN_MAPPED_BUFFER)),
record_filename_("perf.data"),
@@ -237,6 +248,7 @@
double duration_in_sec_;
bool can_dump_kernel_symbols_;
bool dump_symbols_;
+ std::string clockid_;
std::vector<int> cpus_;
EventSelectionSet event_selection_set_;
@@ -325,8 +337,8 @@
} else if (!app_package_name_.empty()) {
// If app process is not created, wait for it. This allows simpleperf starts before
// app process. In this way, we can have a better support of app start-up time profiling.
- int pid = WaitForAppProcess(app_package_name_);
- event_selection_set_.AddMonitoredProcesses({pid});
+ std::set<pid_t> pids = WaitForAppProcesses(app_package_name_);
+ event_selection_set_.AddMonitoredProcesses(pids);
} else {
LOG(ERROR)
<< "No threads to monitor. Try `simpleperf help record` for help";
@@ -498,6 +510,21 @@
<< args[i];
return false;
}
+ } else if (args[i] == "--clockid") {
+ if (!NextArgumentOrError(args, &i)) {
+ return false;
+ }
+ if (args[i] != "perf") {
+ if (!IsSettingClockIdSupported()) {
+ LOG(ERROR) << "Setting clockid is not supported by the kernel.";
+ return false;
+ }
+ if (clockid_map.find(args[i]) == clockid_map.end()) {
+ LOG(ERROR) << "Invalid clockid: " << args[i];
+ return false;
+ }
+ }
+ clockid_ = args[i];
} else if (args[i] == "--cpu") {
if (!NextArgumentOrError(args, &i)) {
return false;
@@ -719,6 +746,9 @@
}
}
event_selection_set_.SetInherit(child_inherit_);
+ if (clockid_ != "perf") {
+ event_selection_set_.SetClockId(clockid_map[clockid_]);
+ }
return true;
}
@@ -1191,6 +1221,7 @@
android::base::GetProperty("ro.product.model", "").c_str(),
android::base::GetProperty("ro.product.name", "").c_str());
#endif
+ info_map["clockid"] = clockid_;
return record_file_writer_->WriteMetaInfoFeature(info_map);
}
diff --git a/simpleperf/cmd_record_test.cpp b/simpleperf/cmd_record_test.cpp
index 47186a5..61228ac 100644
--- a/simpleperf/cmd_record_test.cpp
+++ b/simpleperf/cmd_record_test.cpp
@@ -493,3 +493,17 @@
TEST(record_cmd, exit_with_parent_option) {
ASSERT_TRUE(RunRecordCmd({"--exit-with-parent"}));
}
+
+TEST(record_cmd, clockid_option) {
+ if (!IsSettingClockIdSupported()) {
+ ASSERT_FALSE(RunRecordCmd({"--clockid", "monotonic"}));
+ } else {
+ TemporaryFile tmpfile;
+ ASSERT_TRUE(RunRecordCmd({"--clockid", "monotonic"}, tmpfile.path));
+ std::unique_ptr<RecordFileReader> reader = RecordFileReader::CreateInstance(tmpfile.path);
+ ASSERT_TRUE(reader);
+ std::unordered_map<std::string, std::string> info_map;
+ ASSERT_TRUE(reader->ReadMetaInfoFeature(&info_map));
+ ASSERT_EQ(info_map["clockid"], "monotonic");
+ }
+}
diff --git a/simpleperf/cmd_stat.cpp b/simpleperf/cmd_stat.cpp
index a9d5036..ddd83f7 100644
--- a/simpleperf/cmd_stat.cpp
+++ b/simpleperf/cmd_stat.cpp
@@ -386,8 +386,8 @@
event_selection_set_.AddMonitoredProcesses({workload->GetPid()});
event_selection_set_.SetEnableOnExec(true);
} else if (!app_package_name_.empty()) {
- int pid = WaitForAppProcess(app_package_name_);
- event_selection_set_.AddMonitoredProcesses({pid});
+ std::set<pid_t> pids = WaitForAppProcesses(app_package_name_);
+ event_selection_set_.AddMonitoredProcesses(pids);
} else {
LOG(ERROR)
<< "No threads to monitor. Try `simpleperf help stat` for help\n";
diff --git a/simpleperf/demo/SimpleperfExamplePureJava/app/build/outputs/apk/app-profiling.apk b/simpleperf/demo/SimpleperfExamplePureJava/app/build/outputs/apk/app-profiling.apk
index 0254bc0..f297046 100644
--- a/simpleperf/demo/SimpleperfExamplePureJava/app/build/outputs/apk/app-profiling.apk
+++ b/simpleperf/demo/SimpleperfExamplePureJava/app/build/outputs/apk/app-profiling.apk
Binary files differ
diff --git a/simpleperf/demo/SimpleperfExamplePureJava/app/src/main/AndroidManifest.xml b/simpleperf/demo/SimpleperfExamplePureJava/app/src/main/AndroidManifest.xml
index c611102..f42ec17 100644
--- a/simpleperf/demo/SimpleperfExamplePureJava/app/src/main/AndroidManifest.xml
+++ b/simpleperf/demo/SimpleperfExamplePureJava/app/src/main/AndroidManifest.xml
@@ -17,9 +17,12 @@
</intent-filter>
</activity>
<activity android:name=".SleepActivity"
- android:exported="true">
+ android:exported="true" />
+ <activity android:name=".MultiProcessActivity"
+ android:exported="true" />
- </activity>
+ <service android:name=".MultiProcessService"
+ android:process=":multiprocess_service" />
</application>
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/simpleperf/demo/SimpleperfExamplePureJava/app/src/main/java/com/example/simpleperf/simpleperfexamplepurejava/MultiProcessActivity.java b/simpleperf/demo/SimpleperfExamplePureJava/app/src/main/java/com/example/simpleperf/simpleperfexamplepurejava/MultiProcessActivity.java
new file mode 100644
index 0000000..de698ec
--- /dev/null
+++ b/simpleperf/demo/SimpleperfExamplePureJava/app/src/main/java/com/example/simpleperf/simpleperfexamplepurejava/MultiProcessActivity.java
@@ -0,0 +1,78 @@
+package com.example.simpleperf.simpleperfexamplepurejava;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.util.Log;
+
+public class MultiProcessActivity extends AppCompatActivity {
+ public static final String TAG = "MultiProcessActivity";
+
+ Messenger mService = null;
+ boolean mBound;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_multi_process);
+
+ bindService(new Intent(this, MultiProcessService.class), mConnection,
+ Context.BIND_AUTO_CREATE);
+ createBusyThread();
+ }
+
+ private ServiceConnection mConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
+ mService = new Messenger(iBinder);
+ mBound = true;
+ Message message = new Message();
+ message.what = MultiProcessService.MSG_START_BUSY_THREAD;
+ try {
+ mService.send(message);
+ } catch (RemoteException e) {
+ Log.d(TAG, e.toString());
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName componentName) {
+ mService = null;
+ mBound = false;
+ }
+ };
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+
+ if (mBound) {
+ unbindService(mConnection);
+ mBound = false;
+ }
+ }
+
+ void createBusyThread() {
+ new Thread(new Runnable() {
+ volatile int i = 0;
+
+ @Override
+ public void run() {
+ while (true) {
+ i = callFunction(i);
+ }
+ }
+
+ private int callFunction(int a) {
+ return a+1;
+ }
+ }, "BusyThread").start();
+ }
+}
diff --git a/simpleperf/demo/SimpleperfExamplePureJava/app/src/main/java/com/example/simpleperf/simpleperfexamplepurejava/MultiProcessService.java b/simpleperf/demo/SimpleperfExamplePureJava/app/src/main/java/com/example/simpleperf/simpleperfexamplepurejava/MultiProcessService.java
new file mode 100644
index 0000000..2fd4d57
--- /dev/null
+++ b/simpleperf/demo/SimpleperfExamplePureJava/app/src/main/java/com/example/simpleperf/simpleperfexamplepurejava/MultiProcessService.java
@@ -0,0 +1,50 @@
+package com.example.simpleperf.simpleperfexamplepurejava;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+
+public class MultiProcessService extends Service {
+ public static final int MSG_START_BUSY_THREAD = 1;
+
+ public MultiProcessService() {
+ }
+
+ class IncomingHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_START_BUSY_THREAD:
+ createBusyThread();
+ }
+ super.handleMessage(msg);
+ }
+ }
+
+ final Messenger mMessenger = new Messenger(new IncomingHandler());
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mMessenger.getBinder();
+ }
+
+ void createBusyThread() {
+ new Thread(new Runnable() {
+ volatile int i = 0;
+
+ @Override
+ public void run() {
+ while (true) {
+ i = callFunction(i);
+ }
+ }
+
+ private int callFunction(int a) {
+ return a+1;
+ }
+ }, "BusyService").start();
+ }
+}
diff --git a/simpleperf/demo/SimpleperfExamplePureJava/app/src/main/res/layout/activity_main.xml b/simpleperf/demo/SimpleperfExamplePureJava/app/src/main/res/layout/activity_main.xml
index 1aa4458..4a09b1a 100644
--- a/simpleperf/demo/SimpleperfExamplePureJava/app/src/main/res/layout/activity_main.xml
+++ b/simpleperf/demo/SimpleperfExamplePureJava/app/src/main/res/layout/activity_main.xml
@@ -9,7 +9,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="Hello World!"
+ android:text="MainActivity"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
diff --git a/simpleperf/demo/SimpleperfExamplePureJava/app/src/main/res/layout/activity_multi_process.xml b/simpleperf/demo/SimpleperfExamplePureJava/app/src/main/res/layout/activity_multi_process.xml
new file mode 100644
index 0000000..f97b72e
--- /dev/null
+++ b/simpleperf/demo/SimpleperfExamplePureJava/app/src/main/res/layout/activity_multi_process.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context="com.example.simpleperf.simpleperfexamplepurejava.MultiProcessActivity">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="MultiProcessActivity"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+</android.support.constraint.ConstraintLayout>
diff --git a/simpleperf/demo/SimpleperfExamplePureJava/app/src/main/res/layout/activity_sleep.xml b/simpleperf/demo/SimpleperfExamplePureJava/app/src/main/res/layout/activity_sleep.xml
index e2274ca..f732f77 100644
--- a/simpleperf/demo/SimpleperfExamplePureJava/app/src/main/res/layout/activity_sleep.xml
+++ b/simpleperf/demo/SimpleperfExamplePureJava/app/src/main/res/layout/activity_sleep.xml
@@ -6,4 +6,13 @@
android:layout_height="match_parent"
tools:context="com.example.simpleperf.simpleperfexamplepurejava.SleepActivity">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="SleepActivity"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
</android.support.constraint.ConstraintLayout>
diff --git a/simpleperf/environment.cpp b/simpleperf/environment.cpp
index bf0a061..e238ffb 100644
--- a/simpleperf/environment.cpp
+++ b/simpleperf/environment.cpp
@@ -537,7 +537,8 @@
return false;
}
-int WaitForAppProcess(const std::string& package_name) {
+std::set<pid_t> WaitForAppProcesses(const std::string& package_name) {
+ std::set<pid_t> result;
size_t loop_count = 0;
while (true) {
std::vector<pid_t> pids = GetAllProcesses();
@@ -547,8 +548,14 @@
// Maybe we don't have permission to read it.
continue;
}
- cmdline = android::base::Basename(cmdline);
- if (cmdline != package_name) {
+ std::string process_name = android::base::Basename(cmdline);
+ // The app may have multiple processes, with process name like
+ // com.google.android.googlequicksearchbox:search.
+ size_t split_pos = process_name.find(':');
+ if (split_pos != std::string::npos) {
+ process_name = process_name.substr(0, split_pos);
+ }
+ if (process_name != package_name) {
continue;
}
// If a debuggable app with wrap.sh runs on Android O, the app will be started with
@@ -567,7 +574,10 @@
if (loop_count > 0u) {
LOG(INFO) << "Got process " << pid << " for package " << package_name;
}
- return pid;
+ result.insert(pid);
+ }
+ if (!result.empty()) {
+ return result;
}
if (++loop_count == 1u) {
LOG(INFO) << "Waiting for process of app " << package_name;
diff --git a/simpleperf/environment.h b/simpleperf/environment.h
index 52d0a7c..0f12146 100644
--- a/simpleperf/environment.h
+++ b/simpleperf/environment.h
@@ -92,7 +92,7 @@
ArchType GetMachineArch();
void PrepareVdsoFile();
-int WaitForAppProcess(const std::string& package_name);
+std::set<pid_t> WaitForAppProcesses(const std::string& package_name);
bool RunInAppContext(const std::string& app_package_name, const std::string& cmd,
const std::vector<std::string>& args, size_t workload_args_size,
const std::string& output_filepath, bool need_tracepoint_events);
diff --git a/simpleperf/event_selection_set.cpp b/simpleperf/event_selection_set.cpp
index 240f9d4..ebd3477 100644
--- a/simpleperf/event_selection_set.cpp
+++ b/simpleperf/event_selection_set.cpp
@@ -103,6 +103,19 @@
return false;
}
+bool IsSettingClockIdSupported() {
+ const EventType* type = FindEventTypeByName("cpu-cycles");
+ if (type == nullptr) {
+ return false;
+ }
+ // Check if the kernel supports setting clockid, which was added in kernel 4.0. Just check with
+ // one clockid is enough. Because all needed clockids were supported before kernel 4.0.
+ perf_event_attr attr = CreateDefaultPerfEventAttr(*type);
+ attr.use_clockid = 1;
+ attr.clockid = CLOCK_MONOTONIC;
+ return IsEventAttrSupported(attr);
+}
+
bool EventSelectionSet::BuildAndCheckEventSelection(
const std::string& event_name, EventSelection* selection) {
std::unique_ptr<EventTypeAndModifier> event_type = ParseEventType(event_name);
@@ -372,6 +385,15 @@
}
}
+void EventSelectionSet::SetClockId(int clock_id) {
+ for (auto& group : groups_) {
+ for (auto& selection : group) {
+ selection.event_attr.use_clockid = 1;
+ selection.event_attr.clockid = clock_id;
+ }
+ }
+}
+
bool EventSelectionSet::NeedKernelSymbol() const {
for (const auto& group : groups_) {
for (const auto& selection : group) {
diff --git a/simpleperf/event_selection_set.h b/simpleperf/event_selection_set.h
index cc972be..7397c6f 100644
--- a/simpleperf/event_selection_set.h
+++ b/simpleperf/event_selection_set.h
@@ -101,6 +101,7 @@
void EnableFpCallChainSampling();
bool EnableDwarfCallChainSampling(uint32_t dump_stack_size);
void SetInherit(bool enable);
+ void SetClockId(int clock_id);
bool NeedKernelSymbol() const;
void AddMonitoredProcesses(const std::set<pid_t>& processes) {
@@ -201,5 +202,6 @@
bool IsBranchSamplingSupported();
bool IsDwarfCallChainSamplingSupported();
bool IsDumpingRegsForTracepointEventsSupported();
+bool IsSettingClockIdSupported();
#endif // SIMPLE_PERF_EVENT_SELECTION_SET_H_
diff --git a/simpleperf/scripts/app_profiler.py b/simpleperf/scripts/app_profiler.py
index 9e0f551..c089bbe 100644
--- a/simpleperf/scripts/app_profiler.py
+++ b/simpleperf/scripts/app_profiler.py
@@ -192,13 +192,23 @@
def _find_app_process(self):
- # On Android >= N, pidof is available. Otherwise, we can use ps.
- if self.android_version >= 7:
+ if not self.config['app_package_name'] and self.android_version >= 7:
result, output = self.adb.run_and_return_output(['shell', 'pidof', self.app_program])
- if not result:
- return None
- pid = int(output)
- if self.android_version >= 8 and self.config['app_package_name']:
+ return int(output) if result else None
+ ps_args = ['ps', '-e', '-o', 'PID,NAME'] if self.android_version >= 8 else ['ps']
+ result, output = self.adb.run_and_return_output(['shell'] + ps_args, log_output=False)
+ if not result:
+ return None
+ for line in output.split('\n'):
+ strs = line.split()
+ if len(strs) < 2:
+ continue
+ process_name = strs[-1]
+ if self.config['app_package_name']:
+ # This is to match process names in multiprocess apps.
+ process_name = process_name.split(':')[0]
+ if process_name == self.app_program:
+ pid = int(strs[0] if self.android_version >= 8 else strs[1])
# If a debuggable app with wrap.sh runs on Android O, the app will be started with
# logwrapper as below:
# 1. Zygote forks a child process, rename it to package_name.
@@ -209,16 +219,10 @@
# The problem here is we want to profile the process started in step 4, but
# sometimes we run into the process started in step 1. To solve it, we can check
# if the process has opened an apk file in some app dirs.
- if not self._has_opened_apk_file(pid):
- return None
- return pid
- result, output = self.adb.run_and_return_output(['shell', 'ps'], log_output=False)
- if not result:
- return None
- for line in output.split('\n'):
- strs = line.split()
- if len(strs) > 2 and self.app_program in strs[-1]:
- return int(strs[1])
+ if self.android_version >= 8 and self.config['app_package_name'] and (
+ not self._has_opened_apk_file(pid)):
+ continue
+ return pid
return None
diff --git a/simpleperf/scripts/bin/android/arm/simpleperf b/simpleperf/scripts/bin/android/arm/simpleperf
index c1d7e60..c4d0fce 100755
--- a/simpleperf/scripts/bin/android/arm/simpleperf
+++ b/simpleperf/scripts/bin/android/arm/simpleperf
Binary files differ
diff --git a/simpleperf/scripts/bin/android/arm64/simpleperf b/simpleperf/scripts/bin/android/arm64/simpleperf
index cabad5b..9519f68 100755
--- a/simpleperf/scripts/bin/android/arm64/simpleperf
+++ b/simpleperf/scripts/bin/android/arm64/simpleperf
Binary files differ
diff --git a/simpleperf/scripts/bin/android/x86/simpleperf b/simpleperf/scripts/bin/android/x86/simpleperf
index 32e60b9..b7c753a 100755
--- a/simpleperf/scripts/bin/android/x86/simpleperf
+++ b/simpleperf/scripts/bin/android/x86/simpleperf
Binary files differ
diff --git a/simpleperf/scripts/bin/android/x86_64/simpleperf b/simpleperf/scripts/bin/android/x86_64/simpleperf
index 1ab07d6..069370b 100755
--- a/simpleperf/scripts/bin/android/x86_64/simpleperf
+++ b/simpleperf/scripts/bin/android/x86_64/simpleperf
Binary files differ
diff --git a/simpleperf/scripts/bin/darwin/x86/libsimpleperf_report.dylib b/simpleperf/scripts/bin/darwin/x86/libsimpleperf_report.dylib
index 2a4fa0a..07ff964 100755
--- a/simpleperf/scripts/bin/darwin/x86/libsimpleperf_report.dylib
+++ b/simpleperf/scripts/bin/darwin/x86/libsimpleperf_report.dylib
Binary files differ
diff --git a/simpleperf/scripts/bin/darwin/x86/simpleperf b/simpleperf/scripts/bin/darwin/x86/simpleperf
index f8f6550..61fd1fe 100755
--- a/simpleperf/scripts/bin/darwin/x86/simpleperf
+++ b/simpleperf/scripts/bin/darwin/x86/simpleperf
Binary files differ
diff --git a/simpleperf/scripts/bin/darwin/x86_64/libsimpleperf_report.dylib b/simpleperf/scripts/bin/darwin/x86_64/libsimpleperf_report.dylib
index d9e14ba..f70d7e7 100755
--- a/simpleperf/scripts/bin/darwin/x86_64/libsimpleperf_report.dylib
+++ b/simpleperf/scripts/bin/darwin/x86_64/libsimpleperf_report.dylib
Binary files differ
diff --git a/simpleperf/scripts/bin/darwin/x86_64/simpleperf b/simpleperf/scripts/bin/darwin/x86_64/simpleperf
index da28550..1af4ecf 100755
--- a/simpleperf/scripts/bin/darwin/x86_64/simpleperf
+++ b/simpleperf/scripts/bin/darwin/x86_64/simpleperf
Binary files differ
diff --git a/simpleperf/scripts/bin/linux/x86/libsimpleperf_report.so b/simpleperf/scripts/bin/linux/x86/libsimpleperf_report.so
index e41983a..8d3ea66 100755
--- a/simpleperf/scripts/bin/linux/x86/libsimpleperf_report.so
+++ b/simpleperf/scripts/bin/linux/x86/libsimpleperf_report.so
Binary files differ
diff --git a/simpleperf/scripts/bin/linux/x86/simpleperf b/simpleperf/scripts/bin/linux/x86/simpleperf
index e931f31..fc76b5a 100755
--- a/simpleperf/scripts/bin/linux/x86/simpleperf
+++ b/simpleperf/scripts/bin/linux/x86/simpleperf
Binary files differ
diff --git a/simpleperf/scripts/bin/linux/x86_64/libsimpleperf_report.so b/simpleperf/scripts/bin/linux/x86_64/libsimpleperf_report.so
index 864f1cb..9e57247 100755
--- a/simpleperf/scripts/bin/linux/x86_64/libsimpleperf_report.so
+++ b/simpleperf/scripts/bin/linux/x86_64/libsimpleperf_report.so
Binary files differ
diff --git a/simpleperf/scripts/bin/linux/x86_64/simpleperf b/simpleperf/scripts/bin/linux/x86_64/simpleperf
index 8670bdc..69b0cf9 100755
--- a/simpleperf/scripts/bin/linux/x86_64/simpleperf
+++ b/simpleperf/scripts/bin/linux/x86_64/simpleperf
Binary files differ
diff --git a/simpleperf/scripts/bin/windows/x86/libsimpleperf_report.dll b/simpleperf/scripts/bin/windows/x86/libsimpleperf_report.dll
index 7af9f43..3a37be9 100755
--- a/simpleperf/scripts/bin/windows/x86/libsimpleperf_report.dll
+++ b/simpleperf/scripts/bin/windows/x86/libsimpleperf_report.dll
Binary files differ
diff --git a/simpleperf/scripts/bin/windows/x86/simpleperf.exe b/simpleperf/scripts/bin/windows/x86/simpleperf.exe
index e920733..cce47bf 100755
--- a/simpleperf/scripts/bin/windows/x86/simpleperf.exe
+++ b/simpleperf/scripts/bin/windows/x86/simpleperf.exe
Binary files differ
diff --git a/simpleperf/scripts/bin/windows/x86_64/libsimpleperf_report.dll b/simpleperf/scripts/bin/windows/x86_64/libsimpleperf_report.dll
index 12fd82c..bbe6de6 100755
--- a/simpleperf/scripts/bin/windows/x86_64/libsimpleperf_report.dll
+++ b/simpleperf/scripts/bin/windows/x86_64/libsimpleperf_report.dll
Binary files differ
diff --git a/simpleperf/scripts/bin/windows/x86_64/simpleperf.exe b/simpleperf/scripts/bin/windows/x86_64/simpleperf.exe
index e920733..cce47bf 100755
--- a/simpleperf/scripts/bin/windows/x86_64/simpleperf.exe
+++ b/simpleperf/scripts/bin/windows/x86_64/simpleperf.exe
Binary files differ
diff --git a/simpleperf/scripts/test.py b/simpleperf/scripts/test.py
index c33bdb0..cbdd27b 100644
--- a/simpleperf/scripts/test.py
+++ b/simpleperf/scripts/test.py
@@ -138,17 +138,20 @@
@classmethod
def tearDownClass(cls):
+ if hasattr(cls, 'test_result') and cls.test_result and not cls.test_result.wasSuccessful():
+ return
if hasattr(cls, 'package_name'):
cls.adb.check_run(["uninstall", cls.package_name])
-
- @classmethod
- def cleanupTestFiles(cls):
remove("binary_cache")
remove("annotated_files")
remove("perf.data")
remove("report.txt")
remove("pprof.profile")
+ def run(self, result=None):
+ self.__class__.test_result = result
+ super(TestBase, self).run(result)
+
def run_app_profiler(self, record_arg = "-g --duration 3 -e cpu-cycles:u",
build_binary_cache=True, skip_compile=False, start_activity=True,
native_lib_dir=None, profile_from_launch=False, add_arch=False):
@@ -333,6 +336,16 @@
["com.example.simpleperf.simpleperfexamplepurejava.MainActivity$1.run()",
"__start_thread"])
+ def test_app_profiler_multiprocesses(self):
+ self.adb.check_run(['shell', 'am', 'force-stop', self.package_name])
+ self.adb.check_run(['shell', 'am', 'start', '-n',
+ self.package_name + '/.MultiProcessActivity'])
+ # Wait until both MultiProcessActivity and MultiProcessService set up.
+ time.sleep(3)
+ self.run_app_profiler(skip_compile=True, start_activity=False)
+ self.run_cmd(["report.py", "-o", "report.txt"])
+ self.check_strings_in_file("report.txt", ["BusyService", "BusyThread"])
+
def test_app_profiler_with_ctrl_c(self):
if is_windows():
return
@@ -369,7 +382,7 @@
[("MainActivity.java", 80, 80),
("run", 80, 0),
("callFunction", 0, 0),
- ("line 24", 80, 0)])
+ ("line 23", 80, 0)])
def test_report_sample(self):
self.common_test_report_sample(
@@ -830,9 +843,7 @@
if AdbHelper().get_android_version() < 7:
log_info("Skip tests on Android version < N.")
sys.exit(0)
- test_program = unittest.main(failfast=True, exit=False)
- if test_program.result.wasSuccessful():
- TestExampleBase.cleanupTestFiles()
+ unittest.main(failfast=True)
if __name__ == '__main__':
main()
\ No newline at end of file
diff --git a/verity/build_verity_tree.cpp b/verity/build_verity_tree.cpp
index 7ed51f4..69c761d 100644
--- a/verity/build_verity_tree.cpp
+++ b/verity/build_verity_tree.cpp
@@ -14,6 +14,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <vector>
#include <android-base/file.h>
@@ -125,7 +126,7 @@
{
char *data_filename;
char *verity_filename;
- unsigned char *salt = NULL;
+ std::vector<unsigned char> salt;
size_t salt_size = 0;
bool sparse = false;
size_t block_size = 4096;
@@ -149,12 +150,8 @@
switch (c) {
case 'a':
- salt_size = strlen(optarg);
- salt = new unsigned char[salt_size]();
- if (salt == NULL) {
- FATAL("failed to allocate memory for salt\n");
- }
- memcpy(salt, optarg, salt_size);
+ salt.clear();
+ salt.insert(salt.end(), optarg, &optarg[strlen(optarg)]);
break;
case 'A': {
BIGNUM *bn = NULL;
@@ -162,11 +159,8 @@
FATAL("failed to convert salt from hex\n");
}
salt_size = BN_num_bytes(bn);
- salt = new unsigned char[salt_size]();
- if (salt == NULL) {
- FATAL("failed to allocate memory for salt\n");
- }
- if((size_t)BN_bn2bin(bn, salt) != salt_size) {
+ salt.resize(salt_size);
+ if((size_t)BN_bn2bin(bn, salt.data()) != salt_size) {
FATAL("failed to convert salt to bytes\n");
}
}
@@ -213,19 +207,16 @@
size_t hash_size = EVP_MD_size(md);
assert(hash_size * 2 < block_size);
- if (!salt || !salt_size) {
+ if (salt.data() || !salt_size) {
salt_size = hash_size;
- salt = new unsigned char[salt_size];
- if (salt == NULL) {
- FATAL("failed to allocate memory for salt\n");
- }
+ salt.resize(salt_size);
int random_fd = open("/dev/urandom", O_RDONLY);
if (random_fd < 0) {
FATAL("failed to open /dev/urandom\n");
}
- ssize_t ret = read(random_fd, salt, salt_size);
+ ssize_t ret = read(random_fd, salt.data(), salt_size);
if (ret != (ssize_t)salt_size) {
FATAL("failed to read %zu bytes from /dev/urandom: %zd %d\n", salt_size, ret, errno);
}
@@ -309,14 +300,14 @@
unsigned char zero_block_hash[hash_size];
unsigned char zero_block[block_size];
memset(zero_block, 0, block_size);
- hash_block(md, zero_block, block_size, salt, salt_size, zero_block_hash, NULL);
+ hash_block(md, zero_block, block_size, salt.data(), salt_size, zero_block_hash, NULL);
unsigned char root_hash[hash_size];
verity_tree_levels[levels] = root_hash;
struct sparse_hash_ctx ctx;
ctx.hashes = verity_tree_levels[0];
- ctx.salt = salt;
+ ctx.salt = salt.data();
ctx.salt_size = salt_size;
ctx.hash_size = hash_size;
ctx.block_size = block_size;
@@ -333,7 +324,7 @@
hash_blocks(md,
verity_tree_levels[i], verity_tree_level_blocks[i] * block_size,
verity_tree_levels[i + 1], &out_size,
- salt, salt_size, block_size);
+ salt.data(), salt_size, block_size);
if (i < levels - 1) {
assert(div_round_up(out_size, block_size) == verity_tree_level_blocks[i + 1]);
} else {
@@ -346,7 +337,7 @@
}
printf(" ");
for (size_t i = 0; i < salt_size; i++) {
- printf("%02x", salt[i]);
+ printf("%02x", salt.data()[i]);
}
printf("\n");
@@ -362,5 +353,4 @@
delete[] verity_tree_levels;
delete[] verity_tree_level_blocks;
delete[] verity_tree;
- delete[] salt;
}