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