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