1 /*
2  * Copyright (C) 2015 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 <map>
18 #include <memory>
19 #include <string>
20 #include <vector>
21 
22 #include <android-base/file.h>
23 #include <android-base/strings.h>
24 
25 #include "environment.h"
26 #include "read_elf.h"
27 #include "workload.h"
28 
29 static const std::string SLEEP_SEC = "0.001";
30 
31 void RunWorkloadFunction();
32 void CreateProcesses(size_t count, std::vector<std::unique_ptr<Workload>>* workloads);
33 
34 void ParseSymbol(const ElfFileSymbol& symbol, std::map<std::string, ElfFileSymbol>* symbols);
35 void CheckElfFileSymbols(const std::map<std::string, ElfFileSymbol>& symbols);
36 
37 bool IsRoot();
38 
39 #define TEST_IN_ROOT(TestStatement)                                                                \
40   do {                                                                                             \
41     if (IsRoot()) {                                                                                \
42       TestStatement;                                                                               \
43     } else {                                                                                       \
44       GTEST_LOG_(INFO) << "Didn't test \"" << #TestStatement << "\" requires root privileges";     \
45     }                                                                                              \
46   } while (0)
47 
48 #if defined(__ANDROID__)
49 #define TEST_REQUIRE_HOST_ROOT()
50 #else
51 #define TEST_REQUIRE_HOST_ROOT()  if (!IsRoot()) return
52 #endif
53 
54 bool IsInNativeAbi();
55 // Used to skip tests not supposed to run on non-native ABIs.
56 #define OMIT_TEST_ON_NON_NATIVE_ABIS()  \
57   do { \
58     if (!IsInNativeAbi()) { \
59       GTEST_LOG_(INFO) << "Skip this test as it only runs on native ABIs."; \
60       return; \
61     } \
62   } while (0)
63 
64 bool HasHardwareCounter();
65 #define TEST_REQUIRE_HW_COUNTER() \
66   do { \
67     if (!HasHardwareCounter()) { \
68       GTEST_LOG_(INFO) << "Skip this test as the machine doesn't have hardware PMU counters."; \
69       return; \
70     } \
71   } while (0)
72 
73 bool HasPmuCounter();
74 #define TEST_REQUIRE_PMU_COUNTER() \
75   do { \
76     if (!HasPmuCounter()) { \
77       GTEST_LOG_(INFO) << "Skip this test as the machine doesn't have low-level PMU counters."; \
78       return; \
79     } \
80   } while (0)
81 
82 bool HasTracepointEvents();
83 #define TEST_REQUIRE_TRACEPOINT_EVENTS() \
84   do { \
85     if (!HasTracepointEvents()) { \
86       GTEST_LOG_(INFO) << "Skip this test as the machine doesn't support tracepoint events."; \
87       return; \
88     } \
89   } while (0)
90 
91 #if defined(IN_CTS_TEST)
92 #define TEST_REQUIRE_APPS()
93 #else
94 #define TEST_REQUIRE_APPS() \
95   do { \
96     GTEST_LOG_(INFO) << "Skip this test as test apps aren't available."; \
97     return; \
98   } while (0)
99 #endif
100 
101 class CaptureStdout {
102  public:
CaptureStdout()103   CaptureStdout() : started_(false) {}
104 
~CaptureStdout()105   ~CaptureStdout() {
106     if (started_) {
107       Finish();
108     }
109   }
110 
Start()111   bool Start() {
112     fflush(stdout);
113     old_stdout_ = dup(STDOUT_FILENO);
114     if (old_stdout_ == -1) {
115       return false;
116     }
117     started_ = true;
118     tmpfile_.reset(new TemporaryFile);
119     if (dup2(tmpfile_->fd, STDOUT_FILENO) == -1) {
120       return false;
121     }
122     return true;
123   }
124 
Finish()125   std::string Finish() {
126     fflush(stdout);
127     started_ = false;
128     dup2(old_stdout_, STDOUT_FILENO);
129     close(old_stdout_);
130     std::string s;
131     if (!android::base::ReadFileToString(tmpfile_->path, &s)) {
132       return "";
133     }
134     return s;
135   }
136 
137  private:
138   bool started_;
139   int old_stdout_;
140   std::unique_ptr<TemporaryFile> tmpfile_;
141 };
142 
143 class AppHelper {
144  public:
~AppHelper()145   ~AppHelper() {
146     for (auto& package : installed_packages_) {
147       Workload::RunCmd({"pm", "uninstall", package});
148     }
149   }
150 
InstallApk(const std::string & apk_path,const std::string & package_name)151   bool InstallApk(const std::string& apk_path, const std::string& package_name) {
152     if (Workload::RunCmd({"pm", "install", "-t", "--abi", GetABI(), apk_path})) {
153       installed_packages_.emplace_back(package_name);
154       return true;
155     }
156     return false;
157   }
158 
StartApp(const std::string & start_cmd)159   bool StartApp(const std::string& start_cmd) {
160     app_start_proc_ = Workload::CreateWorkload(android::base::Split(start_cmd, " "));
161     return app_start_proc_ && app_start_proc_->Start();
162   }
163 
164  private:
GetABI()165   const char* GetABI() {
166 #if defined(__i386__)
167     return "x86";
168 #elif defined(__x86_64__)
169     return "x86_64";
170 #elif defined(__aarch64__)
171     return "arm64-v8a";
172 #elif defined(__arm__)
173     return "armeabi-v7a";
174 #else
175     #error "unrecognized ABI"
176 #endif
177   }
178 
179   std::vector<std::string> installed_packages_;
180   std::unique_ptr<Workload> app_start_proc_;
181 };