1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2021 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker // A test to verify that the compilation artifacts built in the system image for all system server
18*795d594fSAndroid Build Coastguard Worker // jars are used. It will fail if odrefresh has run (in which case, artifacts in /data will be used
19*795d594fSAndroid Build Coastguard Worker // instead) or the artifacts in the system image are rejected by the runtime. This test should only
20*795d594fSAndroid Build Coastguard Worker // run on a clean system without any APEX (including com.android.art.testing) installed on data,
21*795d594fSAndroid Build Coastguard Worker // which otherwise will trigger odrefresh.
22*795d594fSAndroid Build Coastguard Worker
23*795d594fSAndroid Build Coastguard Worker #include <stdlib.h>
24*795d594fSAndroid Build Coastguard Worker #include <sys/mman.h>
25*795d594fSAndroid Build Coastguard Worker #include <sys/types.h>
26*795d594fSAndroid Build Coastguard Worker
27*795d594fSAndroid Build Coastguard Worker #include <algorithm>
28*795d594fSAndroid Build Coastguard Worker #include <iterator>
29*795d594fSAndroid Build Coastguard Worker #include <string>
30*795d594fSAndroid Build Coastguard Worker #include <unordered_set>
31*795d594fSAndroid Build Coastguard Worker #include <utility>
32*795d594fSAndroid Build Coastguard Worker #include <vector>
33*795d594fSAndroid Build Coastguard Worker
34*795d594fSAndroid Build Coastguard Worker #include "android-base/properties.h"
35*795d594fSAndroid Build Coastguard Worker #include "android-base/result.h"
36*795d594fSAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
37*795d594fSAndroid Build Coastguard Worker #include "android-base/strings.h"
38*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set.h"
39*795d594fSAndroid Build Coastguard Worker #include "base/common_art_test.h"
40*795d594fSAndroid Build Coastguard Worker #include "base/file_utils.h"
41*795d594fSAndroid Build Coastguard Worker #include "base/os.h"
42*795d594fSAndroid Build Coastguard Worker #include "gmock/gmock.h"
43*795d594fSAndroid Build Coastguard Worker #include "gtest/gtest.h"
44*795d594fSAndroid Build Coastguard Worker #include "oat/oat_file_assistant.h"
45*795d594fSAndroid Build Coastguard Worker #include "procinfo/process_map.h"
46*795d594fSAndroid Build Coastguard Worker
47*795d594fSAndroid Build Coastguard Worker namespace art {
48*795d594fSAndroid Build Coastguard Worker
49*795d594fSAndroid Build Coastguard Worker using ::android::base::Error;
50*795d594fSAndroid Build Coastguard Worker using ::testing::IsSupersetOf;
51*795d594fSAndroid Build Coastguard Worker
52*795d594fSAndroid Build Coastguard Worker constexpr const char* kZygote32 = "zygote";
53*795d594fSAndroid Build Coastguard Worker constexpr const char* kZygote64 = "zygote64";
54*795d594fSAndroid Build Coastguard Worker
GetListFromEnv(const std::string & name)55*795d594fSAndroid Build Coastguard Worker std::vector<std::string> GetListFromEnv(const std::string& name) {
56*795d594fSAndroid Build Coastguard Worker const char* env_value = getenv(name.c_str());
57*795d594fSAndroid Build Coastguard Worker if (env_value == nullptr || strlen(env_value) == 0) {
58*795d594fSAndroid Build Coastguard Worker return {};
59*795d594fSAndroid Build Coastguard Worker }
60*795d594fSAndroid Build Coastguard Worker return android::base::Split(env_value, ":");
61*795d594fSAndroid Build Coastguard Worker }
62*795d594fSAndroid Build Coastguard Worker
GetZygoteNamesAndIsas()63*795d594fSAndroid Build Coastguard Worker android::base::Result<std::vector<std::pair<std::string, InstructionSet>>> GetZygoteNamesAndIsas() {
64*795d594fSAndroid Build Coastguard Worker std::vector<std::pair<std::string, InstructionSet>> names_and_isas;
65*795d594fSAndroid Build Coastguard Worker
66*795d594fSAndroid Build Coastguard Worker // Possible values are: "zygote32", "zygote64", "zygote32_64", "zygote64_32".
67*795d594fSAndroid Build Coastguard Worker std::string zygote_kinds = android::base::GetProperty("ro.zygote", {});
68*795d594fSAndroid Build Coastguard Worker if (zygote_kinds.empty()) {
69*795d594fSAndroid Build Coastguard Worker return Errorf("Unable to get Zygote kinds");
70*795d594fSAndroid Build Coastguard Worker }
71*795d594fSAndroid Build Coastguard Worker
72*795d594fSAndroid Build Coastguard Worker switch (kRuntimeISA) {
73*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm:
74*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm64:
75*795d594fSAndroid Build Coastguard Worker if (zygote_kinds.find("32") != std::string::npos) {
76*795d594fSAndroid Build Coastguard Worker names_and_isas.push_back(std::make_pair(kZygote32, InstructionSet::kArm));
77*795d594fSAndroid Build Coastguard Worker }
78*795d594fSAndroid Build Coastguard Worker if (zygote_kinds.find("64") != std::string::npos) {
79*795d594fSAndroid Build Coastguard Worker names_and_isas.push_back(std::make_pair(kZygote64, InstructionSet::kArm64));
80*795d594fSAndroid Build Coastguard Worker }
81*795d594fSAndroid Build Coastguard Worker break;
82*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86:
83*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86_64:
84*795d594fSAndroid Build Coastguard Worker if (zygote_kinds.find("32") != std::string::npos) {
85*795d594fSAndroid Build Coastguard Worker names_and_isas.push_back(std::make_pair(kZygote32, InstructionSet::kX86));
86*795d594fSAndroid Build Coastguard Worker }
87*795d594fSAndroid Build Coastguard Worker if (zygote_kinds.find("64") != std::string::npos) {
88*795d594fSAndroid Build Coastguard Worker names_and_isas.push_back(std::make_pair(kZygote64, InstructionSet::kX86_64));
89*795d594fSAndroid Build Coastguard Worker }
90*795d594fSAndroid Build Coastguard Worker break;
91*795d594fSAndroid Build Coastguard Worker default:
92*795d594fSAndroid Build Coastguard Worker return Errorf("Unknown runtime ISA: {}", GetInstructionSetString(kRuntimeISA));
93*795d594fSAndroid Build Coastguard Worker }
94*795d594fSAndroid Build Coastguard Worker
95*795d594fSAndroid Build Coastguard Worker return names_and_isas;
96*795d594fSAndroid Build Coastguard Worker }
97*795d594fSAndroid Build Coastguard Worker
GetZygoteExpectedArtifacts(InstructionSet isa)98*795d594fSAndroid Build Coastguard Worker android::base::Result<std::vector<std::string>> GetZygoteExpectedArtifacts(InstructionSet isa) {
99*795d594fSAndroid Build Coastguard Worker std::vector<std::string> jars = GetListFromEnv("DEX2OATBOOTCLASSPATH");
100*795d594fSAndroid Build Coastguard Worker if (jars.empty()) {
101*795d594fSAndroid Build Coastguard Worker return Errorf("Environment variable `DEX2OATBOOTCLASSPATH` is not defined or empty");
102*795d594fSAndroid Build Coastguard Worker }
103*795d594fSAndroid Build Coastguard Worker std::string error_msg;
104*795d594fSAndroid Build Coastguard Worker std::string first_mainline_jar = GetFirstMainlineFrameworkLibraryFilename(&error_msg);
105*795d594fSAndroid Build Coastguard Worker if (first_mainline_jar.empty()) {
106*795d594fSAndroid Build Coastguard Worker return Error() << error_msg;
107*795d594fSAndroid Build Coastguard Worker }
108*795d594fSAndroid Build Coastguard Worker jars.push_back(std::move(first_mainline_jar));
109*795d594fSAndroid Build Coastguard Worker std::string art_root = GetArtRoot();
110*795d594fSAndroid Build Coastguard Worker std::string android_root = GetAndroidRoot();
111*795d594fSAndroid Build Coastguard Worker std::vector<std::string> artifacts;
112*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < jars.size(); i++) {
113*795d594fSAndroid Build Coastguard Worker const std::string& jar = jars[i];
114*795d594fSAndroid Build Coastguard Worker std::string basename =
115*795d594fSAndroid Build Coastguard Worker i == 0 ? "boot.oat" : "boot-" + ReplaceFileExtension(android::base::Basename(jar), "oat");
116*795d594fSAndroid Build Coastguard Worker std::string dir = jar.starts_with(art_root) ? GetPrebuiltPrimaryBootImageDir()
117*795d594fSAndroid Build Coastguard Worker : android_root + "/framework";
118*795d594fSAndroid Build Coastguard Worker std::string oat_file = android::base::StringPrintf(
119*795d594fSAndroid Build Coastguard Worker "%s/%s/%s", dir.c_str(), GetInstructionSetString(isa), basename.c_str());
120*795d594fSAndroid Build Coastguard Worker
121*795d594fSAndroid Build Coastguard Worker if (!OS::FileExists(oat_file.c_str())) {
122*795d594fSAndroid Build Coastguard Worker if (errno == EACCES) {
123*795d594fSAndroid Build Coastguard Worker return ErrnoErrorf("Failed to stat() {}", oat_file);
124*795d594fSAndroid Build Coastguard Worker }
125*795d594fSAndroid Build Coastguard Worker // Dexpreopting is probably disabled. No need to report missing artifacts here because
126*795d594fSAndroid Build Coastguard Worker // artifact generation is already checked at build time.
127*795d594fSAndroid Build Coastguard Worker continue;
128*795d594fSAndroid Build Coastguard Worker }
129*795d594fSAndroid Build Coastguard Worker
130*795d594fSAndroid Build Coastguard Worker artifacts.push_back(oat_file);
131*795d594fSAndroid Build Coastguard Worker }
132*795d594fSAndroid Build Coastguard Worker return artifacts;
133*795d594fSAndroid Build Coastguard Worker }
134*795d594fSAndroid Build Coastguard Worker
GetSystemServerExpectedArtifacts()135*795d594fSAndroid Build Coastguard Worker android::base::Result<std::vector<std::string>> GetSystemServerExpectedArtifacts() {
136*795d594fSAndroid Build Coastguard Worker std::vector<std::string> jars = GetListFromEnv("SYSTEMSERVERCLASSPATH");
137*795d594fSAndroid Build Coastguard Worker if (jars.empty()) {
138*795d594fSAndroid Build Coastguard Worker return Errorf("Environment variable `SYSTEMSERVERCLASSPATH` is not defined or empty");
139*795d594fSAndroid Build Coastguard Worker }
140*795d594fSAndroid Build Coastguard Worker std::vector<std::string> standalone_jars = GetListFromEnv("STANDALONE_SYSTEMSERVER_JARS");
141*795d594fSAndroid Build Coastguard Worker std::move(standalone_jars.begin(), standalone_jars.end(), std::back_inserter(jars));
142*795d594fSAndroid Build Coastguard Worker if (kRuntimeISA == InstructionSet::kNone) {
143*795d594fSAndroid Build Coastguard Worker return Errorf("Unable to get system server ISA");
144*795d594fSAndroid Build Coastguard Worker }
145*795d594fSAndroid Build Coastguard Worker std::vector<std::string> artifacts;
146*795d594fSAndroid Build Coastguard Worker for (const std::string& jar : jars) {
147*795d594fSAndroid Build Coastguard Worker std::string error_msg;
148*795d594fSAndroid Build Coastguard Worker std::string odex_file;
149*795d594fSAndroid Build Coastguard Worker
150*795d594fSAndroid Build Coastguard Worker if (!OatFileAssistant::DexLocationToOdexFilename(jar, kRuntimeISA, &odex_file, &error_msg)) {
151*795d594fSAndroid Build Coastguard Worker return Errorf("Failed to get odex filename: {}", error_msg);
152*795d594fSAndroid Build Coastguard Worker }
153*795d594fSAndroid Build Coastguard Worker
154*795d594fSAndroid Build Coastguard Worker if (!OS::FileExists(odex_file.c_str())) {
155*795d594fSAndroid Build Coastguard Worker if (errno == EACCES) {
156*795d594fSAndroid Build Coastguard Worker return ErrnoErrorf("Failed to stat() {}", odex_file);
157*795d594fSAndroid Build Coastguard Worker }
158*795d594fSAndroid Build Coastguard Worker // Dexpreopting is probably disabled. No need to report missing artifacts here because
159*795d594fSAndroid Build Coastguard Worker // artifact generation is already checked at build time.
160*795d594fSAndroid Build Coastguard Worker continue;
161*795d594fSAndroid Build Coastguard Worker }
162*795d594fSAndroid Build Coastguard Worker
163*795d594fSAndroid Build Coastguard Worker artifacts.push_back(odex_file);
164*795d594fSAndroid Build Coastguard Worker }
165*795d594fSAndroid Build Coastguard Worker return artifacts;
166*795d594fSAndroid Build Coastguard Worker }
167*795d594fSAndroid Build Coastguard Worker
GetMappedFiles(pid_t pid,const std::string & extension,uint16_t flags)168*795d594fSAndroid Build Coastguard Worker android::base::Result<std::vector<std::string>> GetMappedFiles(pid_t pid,
169*795d594fSAndroid Build Coastguard Worker const std::string& extension,
170*795d594fSAndroid Build Coastguard Worker uint16_t flags) {
171*795d594fSAndroid Build Coastguard Worker std::vector<android::procinfo::MapInfo> maps;
172*795d594fSAndroid Build Coastguard Worker if (!android::procinfo::ReadProcessMaps(pid, &maps)) {
173*795d594fSAndroid Build Coastguard Worker return ErrnoErrorf("Failed to get mapped memory regions of pid {}", pid);
174*795d594fSAndroid Build Coastguard Worker }
175*795d594fSAndroid Build Coastguard Worker std::vector<std::string> files;
176*795d594fSAndroid Build Coastguard Worker for (const android::procinfo::MapInfo& map : maps) {
177*795d594fSAndroid Build Coastguard Worker if ((map.flags & flags) && map.name.ends_with(extension)) {
178*795d594fSAndroid Build Coastguard Worker files.push_back(map.name);
179*795d594fSAndroid Build Coastguard Worker }
180*795d594fSAndroid Build Coastguard Worker }
181*795d594fSAndroid Build Coastguard Worker return files;
182*795d594fSAndroid Build Coastguard Worker }
183*795d594fSAndroid Build Coastguard Worker
GetZygoteMappedOatFiles(const std::string & zygote_name)184*795d594fSAndroid Build Coastguard Worker android::base::Result<std::vector<std::string>> GetZygoteMappedOatFiles(
185*795d594fSAndroid Build Coastguard Worker const std::string& zygote_name) {
186*795d594fSAndroid Build Coastguard Worker std::vector<pid_t> pids = art::GetPidByName(zygote_name);
187*795d594fSAndroid Build Coastguard Worker if (pids.empty()) {
188*795d594fSAndroid Build Coastguard Worker return Errorf("Unable to find Zygote process: {}", zygote_name);
189*795d594fSAndroid Build Coastguard Worker }
190*795d594fSAndroid Build Coastguard Worker // OAT files in boot images may not be mmaped with PROT_EXEC if they don't contain executable
191*795d594fSAndroid Build Coastguard Worker // code. Checking PROT_READ is sufficient because an OAT file will be unmapped if the runtime
192*795d594fSAndroid Build Coastguard Worker // rejects it.
193*795d594fSAndroid Build Coastguard Worker return GetMappedFiles(pids[0], ".oat", PROT_READ);
194*795d594fSAndroid Build Coastguard Worker }
195*795d594fSAndroid Build Coastguard Worker
GetSystemServerArtifactsMappedOdexes()196*795d594fSAndroid Build Coastguard Worker android::base::Result<std::vector<std::string>> GetSystemServerArtifactsMappedOdexes() {
197*795d594fSAndroid Build Coastguard Worker std::vector<pid_t> pids = art::GetPidByName("system_server");
198*795d594fSAndroid Build Coastguard Worker if (pids.size() != 1) {
199*795d594fSAndroid Build Coastguard Worker return Errorf("There should be exactly one `system_server` process, found {}", pids.size());
200*795d594fSAndroid Build Coastguard Worker }
201*795d594fSAndroid Build Coastguard Worker return GetMappedFiles(pids[0], ".odex", PROT_READ);
202*795d594fSAndroid Build Coastguard Worker }
203*795d594fSAndroid Build Coastguard Worker
TEST(DexpreoptTest,ForZygote)204*795d594fSAndroid Build Coastguard Worker TEST(DexpreoptTest, ForZygote) {
205*795d594fSAndroid Build Coastguard Worker android::base::Result<std::vector<std::pair<std::string, InstructionSet>>> zygote_names_and_isas =
206*795d594fSAndroid Build Coastguard Worker GetZygoteNamesAndIsas();
207*795d594fSAndroid Build Coastguard Worker ASSERT_RESULT_OK(zygote_names_and_isas);
208*795d594fSAndroid Build Coastguard Worker
209*795d594fSAndroid Build Coastguard Worker for (const auto& [zygote_name, isa] : *zygote_names_and_isas) {
210*795d594fSAndroid Build Coastguard Worker android::base::Result<std::vector<std::string>> expected_artifacts =
211*795d594fSAndroid Build Coastguard Worker GetZygoteExpectedArtifacts(isa);
212*795d594fSAndroid Build Coastguard Worker ASSERT_RESULT_OK(expected_artifacts);
213*795d594fSAndroid Build Coastguard Worker
214*795d594fSAndroid Build Coastguard Worker if (expected_artifacts->empty()) {
215*795d594fSAndroid Build Coastguard Worker // Skip the test if dexpreopting is disabled.
216*795d594fSAndroid Build Coastguard Worker return;
217*795d594fSAndroid Build Coastguard Worker }
218*795d594fSAndroid Build Coastguard Worker
219*795d594fSAndroid Build Coastguard Worker android::base::Result<std::vector<std::string>> mapped_oat_files =
220*795d594fSAndroid Build Coastguard Worker GetZygoteMappedOatFiles(zygote_name);
221*795d594fSAndroid Build Coastguard Worker ASSERT_RESULT_OK(mapped_oat_files);
222*795d594fSAndroid Build Coastguard Worker
223*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(mapped_oat_files.value(), IsSupersetOf(expected_artifacts.value()));
224*795d594fSAndroid Build Coastguard Worker }
225*795d594fSAndroid Build Coastguard Worker }
226*795d594fSAndroid Build Coastguard Worker
TEST(DexpreoptTest,ForSystemServer)227*795d594fSAndroid Build Coastguard Worker TEST(DexpreoptTest, ForSystemServer) {
228*795d594fSAndroid Build Coastguard Worker android::base::Result<std::vector<std::string>> expected_artifacts =
229*795d594fSAndroid Build Coastguard Worker GetSystemServerExpectedArtifacts();
230*795d594fSAndroid Build Coastguard Worker ASSERT_RESULT_OK(expected_artifacts);
231*795d594fSAndroid Build Coastguard Worker
232*795d594fSAndroid Build Coastguard Worker if (expected_artifacts->empty()) {
233*795d594fSAndroid Build Coastguard Worker // Skip the test if dexpreopting is disabled.
234*795d594fSAndroid Build Coastguard Worker return;
235*795d594fSAndroid Build Coastguard Worker }
236*795d594fSAndroid Build Coastguard Worker
237*795d594fSAndroid Build Coastguard Worker android::base::Result<std::vector<std::string>> mapped_odexes =
238*795d594fSAndroid Build Coastguard Worker GetSystemServerArtifactsMappedOdexes();
239*795d594fSAndroid Build Coastguard Worker ASSERT_RESULT_OK(mapped_odexes);
240*795d594fSAndroid Build Coastguard Worker
241*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(mapped_odexes.value(), IsSupersetOf(expected_artifacts.value()));
242*795d594fSAndroid Build Coastguard Worker }
243*795d594fSAndroid Build Coastguard Worker
244*795d594fSAndroid Build Coastguard Worker } // namespace art
245