1 /*
2 * Copyright (C) 2019 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 #include "test/cts/utils.h"
18
19 #include <stdlib.h>
20 #include <sys/system_properties.h>
21
22 #include "perfetto/base/logging.h"
23 #include "perfetto/ext/base/file_utils.h"
24 #include "test/gtest_and_gmock.h"
25
26 namespace perfetto {
27 namespace {
28
29 // invokes |callback| once the target app is in the desired state
PollRunState(bool desired_run_state,base::TestTaskRunner * task_runner,const std::string & name,std::function<void ()> callback)30 void PollRunState(bool desired_run_state,
31 base::TestTaskRunner* task_runner,
32 const std::string& name,
33 std::function<void()> callback) {
34 bool app_running = IsAppRunning(name);
35 if (app_running == desired_run_state) {
36 callback();
37 return;
38 }
39 task_runner->PostDelayedTask(
40 [desired_run_state, task_runner, name, callback] {
41 PollRunState(desired_run_state, task_runner, name, std::move(callback));
42 },
43 /*delay_ms=*/5);
44 }
45
46 } // namespace
47
IsDebuggableBuild()48 bool IsDebuggableBuild() {
49 char buf[PROP_VALUE_MAX + 1] = {};
50 int ret = __system_property_get("ro.debuggable", buf);
51 PERFETTO_CHECK(ret >= 0);
52 return std::string(buf) == "1";
53 }
54
IsUserBuild()55 bool IsUserBuild() {
56 char buf[PROP_VALUE_MAX + 1] = {};
57 int ret = __system_property_get("ro.build.type", buf);
58 PERFETTO_CHECK(ret >= 0);
59 return std::string(buf) == "user";
60 }
61
62 // note: cannot use gtest macros due to return type
IsAppRunning(const std::string & name)63 bool IsAppRunning(const std::string& name) {
64 std::string cmd = "pgrep -f ^" + name + "$";
65 int retcode = system(cmd.c_str());
66 PERFETTO_CHECK(retcode >= 0);
67 int exit_status = WEXITSTATUS(retcode);
68 if (exit_status == 0)
69 return true;
70 if (exit_status == 1)
71 return false;
72 PERFETTO_FATAL("unexpected exit status from system(pgrep): %d", exit_status);
73 }
74
PidForProcessName(const std::string & name)75 int PidForProcessName(const std::string& name) {
76 std::string cmd = "pgrep -f ^" + name + "$";
77 FILE* fp = popen(cmd.c_str(), "re");
78 if (!fp)
79 return -1;
80
81 std::string out;
82 base::ReadFileStream(fp, &out);
83 pclose(fp);
84
85 char* endptr = nullptr;
86 int pid = static_cast<int>(strtol(out.c_str(), &endptr, 10));
87 if (*endptr != '\0' && *endptr != '\n')
88 return -1;
89 return pid;
90 }
91
WaitForProcess(const std::string & process,const std::string & checkpoint_name,base::TestTaskRunner * task_runner,uint32_t delay_ms)92 void WaitForProcess(const std::string& process,
93 const std::string& checkpoint_name,
94 base::TestTaskRunner* task_runner,
95 uint32_t delay_ms) {
96 bool desired_run_state = true;
97 const auto checkpoint = task_runner->CreateCheckpoint(checkpoint_name);
98 task_runner->PostDelayedTask(
99 [desired_run_state, task_runner, process, checkpoint] {
100 PollRunState(desired_run_state, task_runner, process,
101 std::move(checkpoint));
102 },
103 delay_ms);
104 }
105
StartAppActivity(const std::string & app_name,const std::string & activity_name,const std::string & checkpoint_name,base::TestTaskRunner * task_runner,uint32_t delay_ms)106 void StartAppActivity(const std::string& app_name,
107 const std::string& activity_name,
108 const std::string& checkpoint_name,
109 base::TestTaskRunner* task_runner,
110 uint32_t delay_ms) {
111 std::string start_cmd = "am start " + app_name + "/." + activity_name;
112 int status = system(start_cmd.c_str());
113 ASSERT_TRUE(status >= 0 && WEXITSTATUS(status) == 0) << "status: " << status;
114 WaitForProcess(app_name, checkpoint_name, task_runner, delay_ms);
115 }
116
StopApp(const std::string & app_name,const std::string & checkpoint_name,base::TestTaskRunner * task_runner)117 void StopApp(const std::string& app_name,
118 const std::string& checkpoint_name,
119 base::TestTaskRunner* task_runner) {
120 std::string stop_cmd = "am force-stop " + app_name;
121 int status = system(stop_cmd.c_str());
122 ASSERT_TRUE(status >= 0 && WEXITSTATUS(status) == 0) << "status: " << status;
123
124 bool desired_run_state = false;
125 auto checkpoint = task_runner->CreateCheckpoint(checkpoint_name);
126 task_runner->PostTask([desired_run_state, task_runner, app_name, checkpoint] {
127 PollRunState(desired_run_state, task_runner, app_name,
128 std::move(checkpoint));
129 });
130 }
131
StopApp(const std::string & app_name)132 void StopApp(const std::string& app_name) {
133 std::string stop_cmd = "am force-stop " + app_name;
134 system(stop_cmd.c_str());
135 }
136
137 } // namespace perfetto
138