Skip KernelAddressSymbolization on non-debuggable builds
The previous attempt at fixing this using build-time detection
was wrong. CTS package can be built as part of a "user" lunch
combo, but can be run on a userdebug image (and viceversa).
This moves the logic to run-time detection.
Bug: 172272291
Change-Id: Ia46ca9c2f8b7d918bf576adad60c72a0d6d8a782
diff --git a/test/android_test_utils.cc b/test/android_test_utils.cc
new file mode 100644
index 0000000..8c6081a
--- /dev/null
+++ b/test/android_test_utils.cc
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include "test/android_test_utils.h"
+
+#include <stdlib.h>
+#include <sys/system_properties.h>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/file_utils.h"
+
+namespace perfetto {
+namespace {
+
+// invokes |callback| once the target app is in the desired state
+void PollRunState(bool desired_run_state,
+ base::TestTaskRunner* task_runner,
+ const std::string& name,
+ std::function<void()> callback) {
+ bool app_running = IsAppRunning(name);
+ if (app_running == desired_run_state) {
+ callback();
+ return;
+ }
+ task_runner->PostDelayedTask(
+ [desired_run_state, task_runner, name, callback] {
+ PollRunState(desired_run_state, task_runner, name, std::move(callback));
+ },
+ /*delay_ms=*/5);
+}
+
+} // namespace
+
+bool IsDebuggableBuild() {
+ char buf[PROP_VALUE_MAX + 1] = {};
+ int ret = __system_property_get("ro.debuggable", buf);
+ PERFETTO_CHECK(ret >= 0);
+ return std::string(buf) == "1";
+}
+
+bool IsUserBuild() {
+ char buf[PROP_VALUE_MAX + 1] = {};
+ int ret = __system_property_get("ro.build.type", buf);
+ PERFETTO_CHECK(ret >= 0);
+ return std::string(buf) == "user";
+}
+
+// note: cannot use gtest macros due to return type
+bool IsAppRunning(const std::string& name) {
+ std::string cmd = "pgrep -f ^" + name + "$";
+ int retcode = system(cmd.c_str());
+ PERFETTO_CHECK(retcode >= 0);
+ int exit_status = WEXITSTATUS(retcode);
+ if (exit_status == 0)
+ return true;
+ if (exit_status == 1)
+ return false;
+ PERFETTO_FATAL("unexpected exit status from system(pgrep): %d", exit_status);
+}
+
+int PidForProcessName(const std::string& name) {
+ std::string cmd = "pgrep -f ^" + name + "$";
+ FILE* fp = popen(cmd.c_str(), "re");
+ if (!fp)
+ return -1;
+
+ std::string out;
+ base::ReadFileStream(fp, &out);
+ pclose(fp);
+
+ char* endptr = nullptr;
+ int pid = static_cast<int>(strtol(out.c_str(), &endptr, 10));
+ if (*endptr != '\0' && *endptr != '\n')
+ return -1;
+ return pid;
+}
+
+void WaitForProcess(const std::string& process,
+ const std::string& checkpoint_name,
+ base::TestTaskRunner* task_runner,
+ uint32_t delay_ms) {
+ bool desired_run_state = true;
+ const auto checkpoint = task_runner->CreateCheckpoint(checkpoint_name);
+ task_runner->PostDelayedTask(
+ [desired_run_state, task_runner, process, checkpoint] {
+ PollRunState(desired_run_state, task_runner, process,
+ std::move(checkpoint));
+ },
+ delay_ms);
+}
+
+void StartAppActivity(const std::string& app_name,
+ const std::string& activity_name,
+ const std::string& checkpoint_name,
+ base::TestTaskRunner* task_runner,
+ uint32_t delay_ms) {
+ std::string start_cmd = "am start " + app_name + "/." + activity_name;
+ int status = system(start_cmd.c_str());
+ PERFETTO_CHECK(status >= 0 && WEXITSTATUS(status) == 0);
+ WaitForProcess(app_name, checkpoint_name, task_runner, delay_ms);
+}
+
+void StopApp(const std::string& app_name,
+ const std::string& checkpoint_name,
+ base::TestTaskRunner* task_runner) {
+ std::string stop_cmd = "am force-stop " + app_name;
+ int status = system(stop_cmd.c_str());
+ PERFETTO_CHECK(status >= 0 && WEXITSTATUS(status) == 0);
+
+ bool desired_run_state = false;
+ auto checkpoint = task_runner->CreateCheckpoint(checkpoint_name);
+ task_runner->PostTask([desired_run_state, task_runner, app_name, checkpoint] {
+ PollRunState(desired_run_state, task_runner, app_name,
+ std::move(checkpoint));
+ });
+}
+
+void StopApp(const std::string& app_name) {
+ std::string stop_cmd = "am force-stop " + app_name;
+ system(stop_cmd.c_str());
+}
+
+} // namespace perfetto