1 /*
2 * Copyright (C) 2017 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 <cstdlib>
18 #include <fcntl.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23
24 #include <android-base/file.h>
25 #include <android-base/logging.h>
26 #include <android-base/macros.h>
27 #include <android-base/properties.h>
28 #include <android-base/scopeguard.h>
29 #include <android-base/stringprintf.h>
30 #include <android-base/unique_fd.h>
31 #include <binder/Status.h>
32 #include <cutils/properties.h>
33
34 #include <gtest/gtest.h>
35
36 #include <selinux/android.h>
37 #include <selinux/avc.h>
38
39 #include "binder_test_utils.h"
40 #include "dexopt.h"
41 #include "InstalldNativeService.h"
42 #include "installd_constants.h"
43 #include "globals.h"
44 #include "tests/test_utils.h"
45 #include "utils.h"
46 #include "ziparchive/zip_writer.h"
47
48 using android::base::ReadFully;
49 using android::base::unique_fd;
50
51 namespace android {
52 namespace installd {
53
54 constexpr int kTimeoutMs = 60000;
55
56 static const std::string kRuntimeIsa = ABI_STRING;
57
get_property(const char * key,char * value,const char * default_value)58 int get_property(const char *key, char *value, const char *default_value) {
59 return property_get(key, value, default_value);
60 }
61
calculate_oat_file_path(char path[PKG_PATH_MAX],const char * oat_dir,const char * apk_path,const char * instruction_set)62 bool calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
63 const char *instruction_set) {
64 return calculate_oat_file_path_default(path, oat_dir, apk_path, instruction_set);
65 }
66
calculate_odex_file_path(char path[PKG_PATH_MAX],const char * apk_path,const char * instruction_set)67 bool calculate_odex_file_path(char path[PKG_PATH_MAX], const char *apk_path,
68 const char *instruction_set) {
69 return calculate_odex_file_path_default(path, apk_path, instruction_set);
70 }
71
create_cache_path(char path[PKG_PATH_MAX],const char * src,const char * instruction_set)72 bool create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *instruction_set) {
73 return create_cache_path_default(path, src, instruction_set);
74 }
75
force_compile_without_image()76 bool force_compile_without_image() {
77 return false;
78 }
79
run_cmd(const std::string & cmd)80 static void run_cmd(const std::string& cmd) {
81 system(cmd.c_str());
82 }
83
84 template <typename Visitor>
run_cmd_and_process_output(const std::string & cmd,const Visitor & visitor)85 static void run_cmd_and_process_output(const std::string& cmd, const Visitor& visitor) {
86 FILE* file = popen(cmd.c_str(), "r");
87 CHECK(file != nullptr) << "Failed to ptrace " << cmd;
88 char* line = nullptr;
89 while (true) {
90 size_t n = 0u;
91 ssize_t value = getline(&line, &n, file);
92 if (value == -1) {
93 break;
94 }
95 visitor(line);
96 }
97 free(line);
98 fclose(file);
99 }
100
mkdir(const std::string & path,uid_t owner,gid_t group,mode_t mode)101 static int mkdir(const std::string& path, uid_t owner, gid_t group, mode_t mode) {
102 int ret = ::mkdir(path.c_str(), mode);
103 if (ret != 0) {
104 return ret;
105 }
106 ret = ::chown(path.c_str(), owner, group);
107 if (ret != 0) {
108 return ret;
109 }
110 return ::chmod(path.c_str(), mode);
111 }
112
log_callback(int type,const char * fmt,...)113 static int log_callback(int type, const char *fmt, ...) { // NOLINT
114 va_list ap;
115 int priority;
116
117 switch (type) {
118 case SELINUX_WARNING:
119 priority = ANDROID_LOG_WARN;
120 break;
121 case SELINUX_INFO:
122 priority = ANDROID_LOG_INFO;
123 break;
124 default:
125 priority = ANDROID_LOG_ERROR;
126 break;
127 }
128 va_start(ap, fmt);
129 LOG_PRI_VA(priority, "SELinux", fmt, ap);
130 va_end(ap);
131 return 0;
132 }
133
init_selinux()134 static bool init_selinux() {
135 int selinux_enabled = (is_selinux_enabled() > 0);
136
137 union selinux_callback cb;
138 cb.func_log = log_callback;
139 selinux_set_callback(SELINUX_CB_LOG, cb);
140
141 if (selinux_enabled && selinux_status_open(true) < 0) {
142 LOG(ERROR) << "Could not open selinux status; exiting";
143 return false;
144 }
145
146 return true;
147 }
148
149 // Base64 encoding of a simple dex files with 2 methods.
150 static const char kDexFile[] =
151 "UEsDBBQAAAAIAOiOYUs9y6BLCgEAABQCAAALABwAY2xhc3Nlcy5kZXhVVAkAA/Ns+lkOHv1ZdXgL"
152 "AAEEI+UCAASIEwAAS0mt4DIwNmX4qpn7j/2wA7v7N+ZvoQpCJRlVx5SWa4YaiDAxMBQwMDBUhJkI"
153 "MUBBDyMDAzsDRJwFxAdioBDDHAYEYAbiFUAM1M5wAIhFGCGKDIDYAogdgNgDiH2BOAiI0xghekDm"
154 "sQIxGxQzM6ACRijNhCbOhCZfyohdPYyuh8szgtVkMkLsLhAAqeCDi+ejibPZZOZlltgxsDnqZSWW"
155 "JTKwOUFoZh9HayDhZM0g5AMS0M9JzEvX90/KSk0usWZgDAMaws5nAyXBzmpoYGlgAjsAyJoBMp0b"
156 "zQ8gGhbOTEhhzYwU3qxIYc2GFN6MClC/AhUyKUDMAYU9M1Qc5F8GKBscVgIQM0FxCwBQSwECHgMU"
157 "AAAACADojmFLPcugSwoBAAAUAgAACwAYAAAAAAAAAAAAoIEAAAAAY2xhc3Nlcy5kZXhVVAUAA/Ns"
158 "+ll1eAsAAQQj5QIABIgTAABQSwUGAAAAAAEAAQBRAAAATwEAAAAA";
159
160 class DexoptTestEnvTest : public testing::Test {
161 };
162
TEST_F(DexoptTestEnvTest,CheckSelinux)163 TEST_F(DexoptTestEnvTest, CheckSelinux) {
164 ASSERT_EQ(1, is_selinux_enabled());
165
166 // Crude cutout for virtual devices.
167 #if !defined(__i386__) && !defined(__x86_64__)
168 constexpr bool kIsX86 = false;
169 #else
170 constexpr bool kIsX86 = true;
171 #endif
172 ASSERT_TRUE(1 == security_getenforce() || kIsX86 || true /* b/119032200 */);
173 }
174
175 class DexoptTest : public testing::Test {
176 protected:
177 static constexpr bool kDebug = false;
178 static constexpr uid_t kSystemUid = 1000;
179 static constexpr uid_t kSystemGid = 1000;
180 static constexpr int32_t kOSdkVersion = 25;
181 static constexpr int32_t kAppDataFlags = FLAG_STORAGE_CE | FLAG_STORAGE_DE;
182 static constexpr int32_t kTestUserId = 0;
183 static constexpr uid_t kTestAppId = 19999;
184
185 const gid_t kTestAppUid = multiuser_get_uid(kTestUserId, kTestAppId);
186 const uid_t kTestAppGid = multiuser_get_shared_gid(kTestUserId, kTestAppId);
187
188 InstalldNativeService* service_;
189 std::optional<std::string> volume_uuid_;
190 std::string package_name_;
191 std::string apk_path_;
192 std::string dm_file_;
193 std::string app_apk_dir_;
194 std::string app_private_dir_ce_;
195 std::string app_private_dir_de_;
196 std::string se_info_;
197 std::string app_oat_dir_;
198
199 int64_t ce_data_inode_;
200 int64_t de_data_inode_;
201
202 std::string secondary_dex_ce_;
203 std::string secondary_dex_ce_link_;
204 std::string secondary_dex_de_;
205
SetUp()206 virtual void SetUp() {
207 if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
208 GTEST_SKIP() << "Skipping legacy dexopt tests when ART Service is enabled";
209 }
210
211 setenv("ANDROID_LOG_TAGS", "*:v", 1);
212 android::base::InitLogging(nullptr);
213 // Initialize the globals holding the file system main paths (/data/, /system/ etc..).
214 // This is needed in order to compute the application and profile paths.
215 ASSERT_TRUE(init_globals_from_data_and_root());
216 // Initialize selinux log callbacks.
217 // This ensures that selinux is up and running and re-directs the selinux messages
218 // to logcat (in order to make it easier to investigate test results).
219 ASSERT_TRUE(init_selinux());
220 service_ = new InstalldNativeService();
221
222 volume_uuid_ = std::nullopt;
223 package_name_ = "com.installd.test.dexopt";
224 se_info_ = "default";
225 app_apk_dir_ = android_app_dir + package_name_;
226
227 ASSERT_TRUE(create_mock_app());
228 }
229
TearDown()230 virtual void TearDown() {
231 if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
232 GTEST_SKIP();
233 }
234
235 if (!kDebug) {
236 service_->controlDexOptBlocking(false);
237 service_->destroyAppData(
238 volume_uuid_, package_name_, kTestUserId, kAppDataFlags, ce_data_inode_);
239 run_cmd("rm -rf " + app_apk_dir_);
240 run_cmd("rm -rf " + app_private_dir_ce_);
241 run_cmd("rm -rf " + app_private_dir_de_);
242 }
243 delete service_;
244 }
245
create_mock_app()246 ::testing::AssertionResult create_mock_app() {
247 // For debug mode, the directory might already exist. Avoid erroring out.
248 if (mkdir(app_apk_dir_, kSystemUid, kSystemGid, 0755) != 0 && !kDebug) {
249 return ::testing::AssertionFailure() << "Could not create app dir " << app_apk_dir_
250 << " : " << strerror(errno);
251 }
252
253 // Initialize the oat dir path.
254 app_oat_dir_ = app_apk_dir_ + "/oat";
255
256 // Copy the primary apk.
257 apk_path_ = app_apk_dir_ + "/base.jar";
258 std::string error_msg;
259 if (!WriteBase64ToFile(kDexFile, apk_path_, kSystemUid, kSystemGid, 0644, &error_msg)) {
260 return ::testing::AssertionFailure() << "Could not write base64 file to " << apk_path_
261 << " : " << error_msg;
262 }
263
264 // Create the app user data.
265 binder::Status status =
266 service_->createAppData(volume_uuid_, package_name_, kTestUserId, kAppDataFlags,
267 kTestAppUid, 0 /* previousAppId */, se_info_, kOSdkVersion,
268 &ce_data_inode_, &de_data_inode_);
269 if (!status.isOk()) {
270 return ::testing::AssertionFailure() << "Could not create app data: "
271 << status.toString8().c_str();
272 }
273
274 // Create a secondary dex file on CE storage
275 const char* volume_uuid_cstr = volume_uuid_ ? volume_uuid_->c_str() : nullptr;
276 app_private_dir_ce_ = create_data_user_ce_package_path(
277 volume_uuid_cstr, kTestUserId, package_name_.c_str());
278 secondary_dex_ce_ = app_private_dir_ce_ + "/secondary_ce.jar";
279 if (!WriteBase64ToFile(kDexFile,
280 secondary_dex_ce_,
281 kTestAppUid,
282 kTestAppGid,
283 0600,
284 &error_msg)) {
285 return ::testing::AssertionFailure() << "Could not write base64 file to "
286 << secondary_dex_ce_ << " : " << error_msg;
287 }
288 std::string app_private_dir_ce_link = create_data_user_ce_package_path_as_user_link(
289 volume_uuid_cstr, kTestUserId, package_name_.c_str());
290 secondary_dex_ce_link_ = app_private_dir_ce_link + "/secondary_ce.jar";
291
292 // Create a secondary dex file on DE storage.
293 app_private_dir_de_ = create_data_user_de_package_path(
294 volume_uuid_cstr, kTestUserId, package_name_.c_str());
295 secondary_dex_de_ = app_private_dir_de_ + "/secondary_de.jar";
296 if (!WriteBase64ToFile(kDexFile,
297 secondary_dex_de_,
298 kTestAppUid,
299 kTestAppGid,
300 0600,
301 &error_msg)) {
302 return ::testing::AssertionFailure() << "Could not write base64 file to "
303 << secondary_dex_de_ << " : " << error_msg;
304 }
305
306 // Create a non-empty dm file.
307 dm_file_ = apk_path_ + ".dm";
308 {
309 android::base::unique_fd fd(open(dm_file_.c_str(),
310 O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR));
311 if (fd.get() < 0) {
312 return ::testing::AssertionFailure() << "Could not open " << dm_file_;
313 }
314 FILE* file = fdopen(fd.release(), "wb");
315 if (file == nullptr) {
316 return ::testing::AssertionFailure() << "Null file for " << dm_file_
317 << " fd=" << fd.get();
318 }
319
320 // Create a profile file.
321 std::string profile_file = app_private_dir_ce_ + "/primary.prof";
322 run_cmd("profman --generate-test-profile=" + profile_file);
323
324 // Add profile to zip.
325 ZipWriter writer(file);
326 writer.StartEntry("primary.prof", ZipWriter::kCompress);
327 android::base::unique_fd profile_fd(open(profile_file.c_str(), O_RDONLY));
328 if (profile_fd.get() < 0) {
329 return ::testing::AssertionFailure() << "Failed to open profile '"
330 << profile_file << "'";
331 }
332 std::string profile_content;
333 if (!android::base::ReadFdToString(profile_fd, &profile_content)) {
334 return ::testing::AssertionFailure() << "Failed to read profile "
335 << profile_file << "'";
336 }
337 writer.WriteBytes(profile_content.c_str(), profile_content.length());
338 writer.FinishEntry();
339 writer.Finish();
340 fclose(file);
341
342 // Delete the temp file.
343 unlink(profile_file.c_str());
344 }
345
346 // Fix app data uid.
347 status = service_->fixupAppData(volume_uuid_, kTestUserId);
348 if (!status.isOk()) {
349 return ::testing::AssertionFailure() << "Could not fixup app data: "
350 << status.toString8().c_str();
351 }
352
353 return ::testing::AssertionSuccess();
354 }
355
356
GetSecondaryDexArtifact(const std::string & path,const std::string & type)357 std::string GetSecondaryDexArtifact(const std::string& path, const std::string& type) {
358 std::string::size_type end = path.rfind('.');
359 std::string::size_type start = path.rfind('/', end);
360 return path.substr(0, start) + "/oat/" + kRuntimeIsa + "/" +
361 path.substr(start + 1, end - start) + type;
362 }
363
CompileSecondaryDex(const std::string & path,int32_t dex_storage_flag,bool should_binder_call_succeed,bool should_dex_be_compiled=true,binder::Status * binder_result=nullptr,int32_t uid=-1,const char * class_loader_context=nullptr,bool expect_completed=true)364 void CompileSecondaryDex(const std::string& path, int32_t dex_storage_flag,
365 bool should_binder_call_succeed, bool should_dex_be_compiled = true,
366 /*out */ binder::Status* binder_result = nullptr, int32_t uid = -1,
367 const char* class_loader_context = nullptr, bool expect_completed = true) {
368 if (uid == -1) {
369 uid = kTestAppUid;
370 }
371 if (class_loader_context == nullptr) {
372 class_loader_context = "PCL[]";
373 }
374 int32_t dexopt_needed = 0; // does not matter;
375 std::optional<std::string> out_path; // does not matter
376 int32_t dex_flags = DEXOPT_SECONDARY_DEX | dex_storage_flag;
377 std::string compiler_filter = "speed-profile";
378 bool downgrade = false;
379 int32_t target_sdk_version = 0; // default
380 std::optional<std::string> profile_name;
381 std::optional<std::string> dm_path;
382 std::optional<std::string> compilation_reason;
383
384 bool completed = false;
385 binder::Status result = service_->dexopt(path,
386 uid,
387 package_name_,
388 kRuntimeIsa,
389 dexopt_needed,
390 out_path,
391 dex_flags,
392 compiler_filter,
393 volume_uuid_,
394 class_loader_context,
395 se_info_,
396 downgrade,
397 target_sdk_version,
398 profile_name,
399 dm_path,
400 compilation_reason,
401 &completed);
402 ASSERT_EQ(should_binder_call_succeed, result.isOk()) << result.toString8().c_str();
403 ASSERT_EQ(expect_completed, completed);
404 int expected_access = should_dex_be_compiled ? 0 : -1;
405 std::string odex = GetSecondaryDexArtifact(path, "odex");
406 std::string vdex = GetSecondaryDexArtifact(path, "vdex");
407 std::string art = GetSecondaryDexArtifact(path, "art");
408 ASSERT_EQ(expected_access, access(odex.c_str(), R_OK));
409 ASSERT_EQ(expected_access, access(vdex.c_str(), R_OK));
410 ASSERT_EQ(-1, access(art.c_str(), R_OK)); // empty profiles do not generate an image.
411 if (binder_result != nullptr) {
412 *binder_result = result;
413 }
414 }
415
reconcile_secondary_dex(const std::string & path,int32_t storage_flag,bool should_binder_call_succeed,bool should_dex_exist,bool should_dex_be_deleted,int32_t uid=-1,std::string * package_override=nullptr)416 void reconcile_secondary_dex(const std::string& path, int32_t storage_flag,
417 bool should_binder_call_succeed, bool should_dex_exist, bool should_dex_be_deleted,
418 int32_t uid = -1, std::string* package_override = nullptr) {
419 if (uid == -1) {
420 uid = kTestAppUid;
421 }
422 std::vector<std::string> isas;
423 isas.push_back(kRuntimeIsa);
424 bool out_secondary_dex_exists = false;
425 binder::Status result = service_->reconcileSecondaryDexFile(
426 path,
427 package_override == nullptr ? package_name_ : *package_override,
428 uid,
429 isas,
430 volume_uuid_,
431 storage_flag,
432 &out_secondary_dex_exists);
433
434 ASSERT_EQ(should_binder_call_succeed, result.isOk()) << result.toString8().c_str();
435 ASSERT_EQ(should_dex_exist, out_secondary_dex_exists);
436
437 int expected_access = should_dex_be_deleted ? -1 : 0;
438 std::string odex = GetSecondaryDexArtifact(path, "odex");
439 std::string vdex = GetSecondaryDexArtifact(path, "vdex");
440 std::string art = GetSecondaryDexArtifact(path, "art");
441 ASSERT_EQ(expected_access, access(odex.c_str(), F_OK));
442 ASSERT_EQ(expected_access, access(vdex.c_str(), F_OK));
443 ASSERT_EQ(-1, access(art.c_str(), R_OK)); // empty profiles do not generate an image.
444 }
445
CheckFileAccess(const std::string & file,uid_t uid,gid_t gid,mode_t mode)446 void CheckFileAccess(const std::string& file, uid_t uid, gid_t gid, mode_t mode) {
447 struct stat st;
448 ASSERT_EQ(0, stat(file.c_str(), &st));
449 ASSERT_EQ(uid, st.st_uid);
450 ASSERT_EQ(gid, st.st_gid);
451 ASSERT_EQ(mode, st.st_mode);
452 }
453
AssertNoFile(const std::string & file)454 void AssertNoFile(const std::string& file) {
455 struct stat st;
456 ASSERT_EQ(-1, stat(file.c_str(), &st));
457 }
458
CompilePrimaryDexOk(std::string compiler_filter,int32_t dex_flags,const char * oat_dir,int32_t uid,int32_t dexopt_needed,binder::Status * binder_result=nullptr,const char * dm_path=nullptr,bool downgrade=false)459 void CompilePrimaryDexOk(std::string compiler_filter,
460 int32_t dex_flags,
461 const char* oat_dir,
462 int32_t uid,
463 int32_t dexopt_needed,
464 binder::Status* binder_result = nullptr,
465 const char* dm_path = nullptr,
466 bool downgrade = false) {
467 CompilePrimaryDex(compiler_filter,
468 dex_flags,
469 oat_dir,
470 uid,
471 dexopt_needed,
472 dm_path,
473 downgrade,
474 true,
475 true,
476 binder_result);
477 }
478
CompilePrimaryDexFail(std::string compiler_filter,int32_t dex_flags,const char * oat_dir,int32_t uid,int32_t dexopt_needed,binder::Status * binder_result=nullptr,const char * dm_path=nullptr,bool downgrade=false)479 void CompilePrimaryDexFail(std::string compiler_filter,
480 int32_t dex_flags,
481 const char* oat_dir,
482 int32_t uid,
483 int32_t dexopt_needed,
484 binder::Status* binder_result = nullptr,
485 const char* dm_path = nullptr,
486 bool downgrade = false) {
487 CompilePrimaryDex(compiler_filter,
488 dex_flags,
489 oat_dir,
490 uid,
491 dexopt_needed,
492 dm_path,
493 downgrade,
494 false,
495 true,
496 binder_result);
497 }
498
CompilePrimaryDexCancelled(std::string compiler_filter,int32_t dex_flags,const char * oat_dir,int32_t uid,int32_t dexopt_needed,binder::Status * binder_result=nullptr,const char * dm_path=nullptr,bool downgrade=false)499 void CompilePrimaryDexCancelled(std::string compiler_filter,
500 int32_t dex_flags,
501 const char* oat_dir,
502 int32_t uid,
503 int32_t dexopt_needed,
504 binder::Status* binder_result = nullptr,
505 const char* dm_path = nullptr,
506 bool downgrade = false) {
507 CompilePrimaryDex(compiler_filter,
508 dex_flags,
509 oat_dir,
510 uid,
511 dexopt_needed,
512 dm_path,
513 downgrade,
514 true, // should_binder_call_succeed
515 false, // expect_completed
516 binder_result);
517 }
518
CompilePrimaryDex(std::string compiler_filter,int32_t dex_flags,const char * oat_dir,int32_t uid,int32_t dexopt_needed,const char * dm_path,bool downgrade,bool should_binder_call_succeed,bool expect_completed,binder::Status * binder_result)519 void CompilePrimaryDex(std::string compiler_filter,
520 int32_t dex_flags,
521 const char* oat_dir,
522 int32_t uid,
523 int32_t dexopt_needed,
524 const char* dm_path,
525 bool downgrade,
526 bool should_binder_call_succeed,
527 bool expect_completed,
528 /*out */ binder::Status* binder_result) {
529 std::optional<std::string> out_path = oat_dir ? std::make_optional<std::string>(oat_dir) : std::nullopt;
530 std::string class_loader_context = "PCL[]";
531 int32_t target_sdk_version = 0; // default
532 std::string profile_name = "primary.prof";
533 std::optional<std::string> dm_path_opt = dm_path ? std::make_optional<std::string>(dm_path) : std::nullopt;
534 std::string compilation_reason = "test-reason";
535
536 bool prof_result;
537 ASSERT_BINDER_SUCCESS(service_->prepareAppProfile(
538 package_name_, kTestUserId, kTestAppId, profile_name, apk_path_,
539 dm_path_opt, &prof_result));
540 ASSERT_TRUE(prof_result);
541
542 bool completed = false;
543 binder::Status result = service_->dexopt(apk_path_,
544 uid,
545 package_name_,
546 kRuntimeIsa,
547 dexopt_needed,
548 out_path,
549 dex_flags,
550 compiler_filter,
551 volume_uuid_,
552 class_loader_context,
553 se_info_,
554 downgrade,
555 target_sdk_version,
556 profile_name,
557 dm_path_opt,
558 compilation_reason,
559 &completed);
560 ASSERT_EQ(should_binder_call_succeed, result.isOk()) << result.toString8().c_str();
561 ASSERT_EQ(expect_completed, completed);
562
563 if (!should_binder_call_succeed) {
564 if (binder_result != nullptr) {
565 *binder_result = result;
566 }
567 return;
568 }
569 // Check the access to the compiler output.
570 // - speed-profile artifacts are not world-wide readable.
571 // - files are owned by the system uid.
572 std::string odex = GetPrimaryDexArtifact(oat_dir, apk_path_,
573 oat_dir == nullptr ? "dex" : "odex");
574 std::string vdex = GetPrimaryDexArtifact(oat_dir, apk_path_, "vdex");
575 std::string art = GetPrimaryDexArtifact(oat_dir, apk_path_, "art");
576
577 bool is_public = (dex_flags & DEXOPT_PUBLIC) != 0;
578 mode_t mode = S_IFREG | (is_public ? 0644 : 0640);
579 if (expect_completed) {
580 CheckFileAccess(odex, kSystemUid, uid, mode);
581 CheckFileAccess(vdex, kSystemUid, uid, mode);
582 } else {
583 AssertNoFile(odex);
584 AssertNoFile(vdex);
585 }
586
587 if (compiler_filter == "speed-profile") {
588 if (expect_completed) {
589 CheckFileAccess(art, kSystemUid, uid, mode);
590 } else {
591 AssertNoFile(art);
592 }
593 }
594 if (binder_result != nullptr) {
595 *binder_result = result;
596 }
597 }
598
GetPrimaryDexArtifact(const char * oat_dir,const std::string & dex_path,const std::string & type)599 std::string GetPrimaryDexArtifact(const char* oat_dir,
600 const std::string& dex_path,
601 const std::string& type) {
602 if (oat_dir == nullptr) {
603 std::string path = dex_path;
604 for (auto it = path.begin() + 1; it < path.end(); ++it) {
605 if (*it == '/') {
606 *it = '@';
607 }
608 }
609 return android_data_dir + DALVIK_CACHE + '/' + kRuntimeIsa + "/" + path
610 + "@classes." + type;
611 } else {
612 std::string::size_type name_end = dex_path.rfind('.');
613 std::string::size_type name_start = dex_path.rfind('/');
614 return std::string(oat_dir) + "/" + kRuntimeIsa + "/" +
615 dex_path.substr(name_start + 1, name_end - name_start) + type;
616 }
617 }
618
GetSize(const std::string & path)619 int64_t GetSize(const std::string& path) {
620 struct stat file_stat;
621 if (stat(path.c_str(), &file_stat) == 0) {
622 return static_cast<int64_t>(file_stat.st_size);
623 }
624 PLOG(ERROR) << "Cannot stat path: " << path;
625 return -1;
626 }
627
TestDeleteOdex(bool in_dalvik_cache)628 void TestDeleteOdex(bool in_dalvik_cache) {
629 const char* oat_dir = in_dalvik_cache ? nullptr : app_oat_dir_.c_str();
630 CompilePrimaryDexOk(
631 "speed-profile",
632 DEXOPT_BOOTCOMPLETE | DEXOPT_PROFILE_GUIDED | DEXOPT_PUBLIC
633 | DEXOPT_GENERATE_APP_IMAGE,
634 oat_dir,
635 kTestAppGid,
636 DEX2OAT_FROM_SCRATCH,
637 /*binder_result=*/nullptr,
638 dm_file_.c_str());
639
640
641 int64_t odex_size = GetSize(GetPrimaryDexArtifact(oat_dir, apk_path_,
642 in_dalvik_cache ? "dex" : "odex"));
643 int64_t vdex_size = GetSize(GetPrimaryDexArtifact(oat_dir, apk_path_, "vdex"));
644 int64_t art_size = GetSize(GetPrimaryDexArtifact(oat_dir, apk_path_, "art"));
645
646 LOG(ERROR) << "test odex " << odex_size;
647 LOG(ERROR) << "test vdex_size " << vdex_size;
648 LOG(ERROR) << "test art_size " << art_size;
649 int64_t expected_bytes_freed = odex_size + vdex_size + art_size;
650
651 int64_t bytes_freed;
652 binder::Status result = service_->deleteOdex(
653 package_name_,
654 apk_path_,
655 kRuntimeIsa,
656 in_dalvik_cache ? std::nullopt : std::make_optional<std::string>(app_oat_dir_.c_str()),
657 &bytes_freed);
658 ASSERT_TRUE(result.isOk()) << result.toString8().c_str();
659
660 ASSERT_GE(odex_size, 0);
661 ASSERT_GE(vdex_size, 0);
662 ASSERT_GE(art_size, 0);
663
664 ASSERT_EQ(expected_bytes_freed, bytes_freed);
665 }
666
checkVisibility(bool in_dalvik_cache,int32_t expected_visibility)667 void checkVisibility(bool in_dalvik_cache, int32_t expected_visibility) {
668 int32_t visibility;
669 ASSERT_BINDER_SUCCESS(service_->getOdexVisibility(package_name_, apk_path_, kRuntimeIsa,
670 in_dalvik_cache
671 ? std::nullopt
672 : std::make_optional<std::string>(
673 app_oat_dir_.c_str()),
674 &visibility));
675 EXPECT_EQ(visibility, expected_visibility);
676 }
677
TestGetOdexVisibility(bool in_dalvik_cache)678 void TestGetOdexVisibility(bool in_dalvik_cache) {
679 const char* oat_dir = in_dalvik_cache ? nullptr : app_oat_dir_.c_str();
680
681 checkVisibility(in_dalvik_cache, ODEX_NOT_FOUND);
682
683 CompilePrimaryDexOk("speed-profile",
684 DEXOPT_BOOTCOMPLETE | DEXOPT_PROFILE_GUIDED | DEXOPT_PUBLIC |
685 DEXOPT_GENERATE_APP_IMAGE,
686 oat_dir, kTestAppGid, DEX2OAT_FROM_SCRATCH,
687 /*binder_result=*/nullptr, dm_file_.c_str());
688 checkVisibility(in_dalvik_cache, ODEX_IS_PUBLIC);
689
690 CompilePrimaryDexOk("speed-profile",
691 DEXOPT_BOOTCOMPLETE | DEXOPT_PROFILE_GUIDED | DEXOPT_GENERATE_APP_IMAGE,
692 oat_dir, kTestAppGid, DEX2OAT_FROM_SCRATCH,
693 /*binder_result=*/nullptr, dm_file_.c_str());
694 checkVisibility(in_dalvik_cache, ODEX_IS_PRIVATE);
695 }
696 };
697
698
TEST_F(DexoptTest,DexoptSecondaryCe)699 TEST_F(DexoptTest, DexoptSecondaryCe) {
700 LOG(INFO) << "DexoptSecondaryCe";
701 CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE,
702 /*binder_ok*/ true, /*compile_ok*/ true);
703 }
704
TEST_F(DexoptTest,DexoptSecondaryCeLink)705 TEST_F(DexoptTest, DexoptSecondaryCeLink) {
706 LOG(INFO) << "DexoptSecondaryCeLink";
707 CompileSecondaryDex(secondary_dex_ce_link_, DEXOPT_STORAGE_CE,
708 /*binder_ok*/ true, /*compile_ok*/ true);
709 }
710
TEST_F(DexoptTest,DexoptSecondaryCeWithContext)711 TEST_F(DexoptTest, DexoptSecondaryCeWithContext) {
712 LOG(INFO) << "DexoptSecondaryCeWithContext";
713 std::string class_loader_context = "PCL[" + secondary_dex_ce_ + "]";
714 CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE,
715 /*binder_ok*/ true, /*compile_ok*/ true, nullptr, -1, class_loader_context.c_str());
716 }
717
TEST_F(DexoptTest,DexoptSecondaryDe)718 TEST_F(DexoptTest, DexoptSecondaryDe) {
719 LOG(INFO) << "DexoptSecondaryDe";
720 CompileSecondaryDex(secondary_dex_de_, DEXOPT_STORAGE_DE,
721 /*binder_ok*/ true, /*compile_ok*/ true);
722 }
723
TEST_F(DexoptTest,DexoptSecondaryDeWithContext)724 TEST_F(DexoptTest, DexoptSecondaryDeWithContext) {
725 LOG(INFO) << "DexoptSecondaryDeWithContext";
726 std::string class_loader_context = "PCL[" + secondary_dex_de_ + "]";
727 CompileSecondaryDex(secondary_dex_de_, DEXOPT_STORAGE_DE,
728 /*binder_ok*/ true, /*compile_ok*/ true, nullptr, -1, class_loader_context.c_str());
729 }
730
TEST_F(DexoptTest,DexoptSecondaryDoesNotExist)731 TEST_F(DexoptTest, DexoptSecondaryDoesNotExist) {
732 LOG(INFO) << "DexoptSecondaryDoesNotExist";
733 // If the file validates but does not exist we do not treat it as an error.
734 binder::Status status;
735 CompileSecondaryDex(secondary_dex_ce_ + "not.there", DEXOPT_STORAGE_CE,
736 /*binder_ok*/ true, /*compile_ok*/ false, &status);
737 EXPECT_STREQ(status.toString8().c_str(), "No error");
738 }
739
TEST_F(DexoptTest,DexoptSecondaryStorageValidationError)740 TEST_F(DexoptTest, DexoptSecondaryStorageValidationError) {
741 LOG(INFO) << "DexoptSecondaryStorageValidationError";
742 binder::Status status;
743 CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_DE,
744 /*binder_ok*/ false, /*compile_ok*/ false, &status);
745 EXPECT_STREQ(status.toString8().c_str(),
746 "Status(-8, EX_SERVICE_SPECIFIC): '-1: Dexoptanalyzer path validation failed'");
747 }
748
TEST_F(DexoptTest,DexoptSecondaryAppOwnershipValidationError)749 TEST_F(DexoptTest, DexoptSecondaryAppOwnershipValidationError) {
750 LOG(INFO) << "DexoptSecondaryAppOwnershipValidationError";
751 binder::Status status;
752 CompileSecondaryDex("/data/data/random.app/secondary.jar", DEXOPT_STORAGE_CE,
753 /*binder_ok*/ false, /*compile_ok*/ false, &status);
754 EXPECT_STREQ(status.toString8().c_str(),
755 "Status(-8, EX_SERVICE_SPECIFIC): '-1: Dexoptanalyzer path validation failed'");
756 }
757
TEST_F(DexoptTest,DexoptSecondaryAcessViaDifferentUidError)758 TEST_F(DexoptTest, DexoptSecondaryAcessViaDifferentUidError) {
759 LOG(INFO) << "DexoptSecondaryAcessViaDifferentUidError";
760 binder::Status status;
761 CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE,
762 /*binder_ok*/ false, /*compile_ok*/ false, &status, kSystemUid);
763 EXPECT_STREQ(status.toString8().c_str(),
764 "Status(-8, EX_SERVICE_SPECIFIC): '-1: Dexoptanalyzer open zip failed'");
765 }
766
TEST_F(DexoptTest,DexoptPrimaryPublic)767 TEST_F(DexoptTest, DexoptPrimaryPublic) {
768 LOG(INFO) << "DexoptPrimaryPublic";
769 CompilePrimaryDexOk("verify",
770 DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC,
771 app_oat_dir_.c_str(),
772 kTestAppGid,
773 DEX2OAT_FROM_SCRATCH);
774 }
775
TEST_F(DexoptTest,DexoptPrimaryPublicCreateOatDir)776 TEST_F(DexoptTest, DexoptPrimaryPublicCreateOatDir) {
777 LOG(INFO) << "DexoptPrimaryPublic";
778 ASSERT_BINDER_SUCCESS(service_->createOatDir(package_name_, app_oat_dir_, kRuntimeIsa));
779 CompilePrimaryDexOk("verify",
780 DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC,
781 app_oat_dir_.c_str(),
782 kTestAppGid,
783 DEX2OAT_FROM_SCRATCH);
784 }
785
TEST_F(DexoptTest,DexoptPrimaryPublicRestore)786 TEST_F(DexoptTest, DexoptPrimaryPublicRestore) {
787 LOG(INFO) << "DexoptPrimaryPublicRestore";
788 CompilePrimaryDexOk("verify",
789 DEXOPT_FOR_RESTORE | DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC,
790 app_oat_dir_.c_str(),
791 kTestAppGid,
792 DEX2OAT_FROM_SCRATCH);
793 }
794
TEST_F(DexoptTest,DexoptPrimaryFailedInvalidFilter)795 TEST_F(DexoptTest, DexoptPrimaryFailedInvalidFilter) {
796 LOG(INFO) << "DexoptPrimaryFailedInvalidFilter";
797 binder::Status status;
798 CompilePrimaryDexFail("awesome-filter",
799 DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PUBLIC,
800 app_oat_dir_.c_str(),
801 kTestAppGid,
802 DEX2OAT_FROM_SCRATCH,
803 &status);
804 EXPECT_STREQ(status.toString8().c_str(),
805 "Status(-8, EX_SERVICE_SPECIFIC): \'256: Dex2oat invocation for "
806 "/data/app/com.installd.test.dexopt/base.jar failed: dex2oat error'");
807 }
808
TEST_F(DexoptTest,DexoptPrimaryProfileNonPublic)809 TEST_F(DexoptTest, DexoptPrimaryProfileNonPublic) {
810 LOG(INFO) << "DexoptPrimaryProfileNonPublic";
811 CompilePrimaryDexOk("speed-profile",
812 DEXOPT_BOOTCOMPLETE | DEXOPT_PROFILE_GUIDED | DEXOPT_GENERATE_APP_IMAGE,
813 app_oat_dir_.c_str(),
814 kTestAppGid,
815 DEX2OAT_FROM_SCRATCH,
816 /*binder_result=*/nullptr,
817 dm_file_.c_str());
818 }
819
TEST_F(DexoptTest,DexoptPrimaryProfilePublic)820 TEST_F(DexoptTest, DexoptPrimaryProfilePublic) {
821 LOG(INFO) << "DexoptPrimaryProfilePublic";
822 CompilePrimaryDexOk("speed-profile",
823 DEXOPT_BOOTCOMPLETE | DEXOPT_PROFILE_GUIDED | DEXOPT_PUBLIC |
824 DEXOPT_GENERATE_APP_IMAGE,
825 app_oat_dir_.c_str(),
826 kTestAppGid,
827 DEX2OAT_FROM_SCRATCH,
828 /*binder_result=*/nullptr,
829 dm_file_.c_str());
830 }
831
TEST_F(DexoptTest,DexoptPrimaryBackgroundOk)832 TEST_F(DexoptTest, DexoptPrimaryBackgroundOk) {
833 LOG(INFO) << "DexoptPrimaryBackgroundOk";
834 CompilePrimaryDexOk("speed-profile",
835 DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PROFILE_GUIDED |
836 DEXOPT_GENERATE_APP_IMAGE,
837 app_oat_dir_.c_str(),
838 kTestAppGid,
839 DEX2OAT_FROM_SCRATCH,
840 /*binder_result=*/nullptr,
841 dm_file_.c_str());
842 }
843
TEST_F(DexoptTest,DexoptBlockPrimary)844 TEST_F(DexoptTest, DexoptBlockPrimary) {
845 LOG(INFO) << "DexoptPrimaryPublic";
846 service_->controlDexOptBlocking(true);
847 CompilePrimaryDexCancelled("verify",
848 DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC,
849 app_oat_dir_.c_str(),
850 kTestAppGid,
851 DEX2OAT_FROM_SCRATCH, nullptr, nullptr);
852 service_->controlDexOptBlocking(false);
853 }
854
TEST_F(DexoptTest,DexoptUnblockPrimary)855 TEST_F(DexoptTest, DexoptUnblockPrimary) {
856 LOG(INFO) << "DexoptPrimaryPublic";
857 service_->controlDexOptBlocking(true);
858 service_->controlDexOptBlocking(false);
859 CompilePrimaryDexOk("verify",
860 DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC,
861 app_oat_dir_.c_str(),
862 kTestAppGid,
863 DEX2OAT_FROM_SCRATCH, nullptr, nullptr);
864 }
865
TEST_F(DexoptTest,DeleteDexoptArtifactsData)866 TEST_F(DexoptTest, DeleteDexoptArtifactsData) {
867 LOG(INFO) << "DeleteDexoptArtifactsData";
868 TestDeleteOdex(/*in_dalvik_cache=*/ false);
869 }
870
TEST_F(DexoptTest,DeleteDexoptArtifactsDalvikCache)871 TEST_F(DexoptTest, DeleteDexoptArtifactsDalvikCache) {
872 LOG(INFO) << "DeleteDexoptArtifactsDalvikCache";
873 TestDeleteOdex(/*in_dalvik_cache=*/ true);
874 }
875
TEST_F(DexoptTest,GetOdexVisibilityData)876 TEST_F(DexoptTest, GetOdexVisibilityData) {
877 LOG(INFO) << "GetOdexVisibilityData";
878 TestGetOdexVisibility(/*in_dalvik_cache=*/false);
879 }
880
TEST_F(DexoptTest,GetOdexVisibilityDalvikCache)881 TEST_F(DexoptTest, GetOdexVisibilityDalvikCache) {
882 LOG(INFO) << "GetOdexVisibilityDalvikCache";
883 TestGetOdexVisibility(/*in_dalvik_cache=*/true);
884 }
885
TEST_F(DexoptTest,ResolveStartupConstStrings)886 TEST_F(DexoptTest, ResolveStartupConstStrings) {
887 LOG(INFO) << "DexoptDex2oatResolveStartupStrings";
888 const std::string property = "persist.device_config.runtime.dex2oat_resolve_startup_strings";
889 const std::string previous_value = android::base::GetProperty(property, "");
890 auto restore_property = android::base::make_scope_guard([=]() {
891 android::base::SetProperty(property, previous_value);
892 });
893 std::string odex = GetPrimaryDexArtifact(app_oat_dir_.c_str(), apk_path_, "odex");
894 // Disable the property to start.
895 bool found_disable = false;
896 ASSERT_TRUE(android::base::SetProperty(property, "false")) << property;
897 CompilePrimaryDexOk("speed-profile",
898 DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PROFILE_GUIDED |
899 DEXOPT_GENERATE_APP_IMAGE,
900 app_oat_dir_.c_str(),
901 kTestAppGid,
902 DEX2OAT_FROM_SCRATCH,
903 /*binder_result=*/nullptr,
904 dm_file_.c_str());
905 run_cmd_and_process_output(
906 "oatdump --header-only --oat-file=" + odex,
907 [&](const std::string& line) {
908 if (line.find("--resolve-startup-const-strings=false") != std::string::npos) {
909 found_disable = true;
910 }
911 });
912 EXPECT_TRUE(found_disable);
913 // Enable the property and inspect that .art artifact is larger.
914 bool found_enable = false;
915 ASSERT_TRUE(android::base::SetProperty(property, "true")) << property;
916 CompilePrimaryDexOk("speed-profile",
917 DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PROFILE_GUIDED |
918 DEXOPT_GENERATE_APP_IMAGE,
919 app_oat_dir_.c_str(),
920 kTestAppGid,
921 DEX2OAT_FROM_SCRATCH,
922 /*binder_result=*/nullptr,
923 dm_file_.c_str());
924 run_cmd_and_process_output(
925 "oatdump --header-only --oat-file=" + odex,
926 [&](const std::string& line) {
927 if (line.find("--resolve-startup-const-strings=true") != std::string::npos) {
928 found_enable = true;
929 }
930 });
931 EXPECT_TRUE(found_enable);
932 }
933
TEST_F(DexoptTest,DexoptDex2oat64Enabled)934 TEST_F(DexoptTest, DexoptDex2oat64Enabled) {
935 LOG(INFO) << "DexoptDex2oat64Enabled";
936 std::string zygote_prop = android::base::GetProperty("ro.zygote", "");
937 ASSERT_GT(zygote_prop.size(), 0);
938 if (zygote_prop != "zygote32_64" && zygote_prop != "zygote64_32") {
939 GTEST_SKIP() << "DexoptDex2oat64Enabled skipped for single-bitness Zygote.";
940 }
941 const std::string property = "dalvik.vm.dex2oat64.enabled";
942 const std::string previous_value = android::base::GetProperty(property, "");
943 auto restore_property = android::base::make_scope_guard([=]() {
944 android::base::SetProperty(property, previous_value);
945 });
946 std::string odex = GetPrimaryDexArtifact(app_oat_dir_.c_str(), apk_path_, "odex");
947 // Disable the property and use dex2oat32.
948 ASSERT_TRUE(android::base::SetProperty(property, "false")) << property;
949 CompilePrimaryDexOk("speed-profile",
950 DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PROFILE_GUIDED |
951 DEXOPT_GENERATE_APP_IMAGE,
952 app_oat_dir_.c_str(),
953 kTestAppGid,
954 DEX2OAT_FROM_SCRATCH,
955 /*binder_result=*/nullptr,
956 dm_file_.c_str());
957 // Enable the property and use dex2oat64.
958 ASSERT_TRUE(android::base::SetProperty(property, "true")) << property;
959 CompilePrimaryDexOk("speed-profile",
960 DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PROFILE_GUIDED |
961 DEXOPT_GENERATE_APP_IMAGE,
962 app_oat_dir_.c_str(),
963 kTestAppGid,
964 DEX2OAT_FROM_SCRATCH,
965 /*binder_result=*/nullptr,
966 dm_file_.c_str());
967 }
968
969 class PrimaryDexReCompilationTest : public DexoptTest {
970 public:
SetUp()971 virtual void SetUp() {
972 if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
973 GTEST_SKIP() << "Skipping legacy dexopt tests when ART Service is enabled";
974 }
975
976 DexoptTest::SetUp();
977 CompilePrimaryDexOk("verify",
978 DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC,
979 app_oat_dir_.c_str(),
980 kTestAppGid,
981 DEX2OAT_FROM_SCRATCH);
982 std::string odex = GetSecondaryDexArtifact(apk_path_, "odex");
983 std::string vdex = GetSecondaryDexArtifact(apk_path_, "vdex");
984
985 first_compilation_odex_fd_.reset(open(odex.c_str(), O_RDONLY));
986 first_compilation_vdex_fd_.reset(open(vdex.c_str(), O_RDONLY));
987 }
988
TearDown()989 virtual void TearDown() {
990 if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
991 GTEST_SKIP();
992 }
993
994 first_compilation_odex_fd_.reset(-1);
995 first_compilation_vdex_fd_.reset(-1);
996 DexoptTest::TearDown();
997 }
998
999 protected:
1000 unique_fd first_compilation_odex_fd_;
1001 unique_fd first_compilation_vdex_fd_;
1002 };
1003
TEST_F(PrimaryDexReCompilationTest,DexoptPrimaryUpdateInPlaceVdex)1004 TEST_F(PrimaryDexReCompilationTest, DexoptPrimaryUpdateInPlaceVdex) {
1005 LOG(INFO) << "DexoptPrimaryUpdateInPlaceVdex";
1006
1007 CompilePrimaryDexOk("verify",
1008 DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PUBLIC,
1009 app_oat_dir_.c_str(),
1010 kTestAppGid,
1011 DEX2OAT_FOR_BOOT_IMAGE);
1012 }
1013
1014 class ReconcileTest : public DexoptTest {
SetUp()1015 virtual void SetUp() {
1016 if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
1017 GTEST_SKIP() << "Skipping legacy dexopt tests when ART Service is enabled";
1018 }
1019
1020 DexoptTest::SetUp();
1021 CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE,
1022 /*binder_ok*/ true, /*compile_ok*/ true);
1023 CompileSecondaryDex(secondary_dex_de_, DEXOPT_STORAGE_DE,
1024 /*binder_ok*/ true, /*compile_ok*/ true);
1025 }
1026 };
1027
TEST_F(ReconcileTest,ReconcileSecondaryCeExists)1028 TEST_F(ReconcileTest, ReconcileSecondaryCeExists) {
1029 LOG(INFO) << "ReconcileSecondaryCeExists";
1030 reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_CE,
1031 /*binder_ok*/ true, /*dex_ok */ true, /*odex_deleted*/ false);
1032 }
1033
TEST_F(ReconcileTest,ReconcileSecondaryCeLinkExists)1034 TEST_F(ReconcileTest, ReconcileSecondaryCeLinkExists) {
1035 LOG(INFO) << "ReconcileSecondaryCeLinkExists";
1036 reconcile_secondary_dex(secondary_dex_ce_link_, FLAG_STORAGE_CE,
1037 /*binder_ok*/ true, /*dex_ok */ true, /*odex_deleted*/ false);
1038 }
1039
TEST_F(ReconcileTest,ReconcileSecondaryDeExists)1040 TEST_F(ReconcileTest, ReconcileSecondaryDeExists) {
1041 LOG(INFO) << "ReconcileSecondaryDeExists";
1042 reconcile_secondary_dex(secondary_dex_de_, FLAG_STORAGE_DE,
1043 /*binder_ok*/ true, /*dex_ok */ true, /*odex_deleted*/ false);
1044 }
1045
TEST_F(ReconcileTest,ReconcileSecondaryDeDoesNotExist)1046 TEST_F(ReconcileTest, ReconcileSecondaryDeDoesNotExist) {
1047 LOG(INFO) << "ReconcileSecondaryDeDoesNotExist";
1048 run_cmd("rm -rf " + secondary_dex_de_);
1049 reconcile_secondary_dex(secondary_dex_de_, FLAG_STORAGE_DE,
1050 /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ true);
1051 }
1052
TEST_F(ReconcileTest,ReconcileSecondaryStorageValidationError)1053 TEST_F(ReconcileTest, ReconcileSecondaryStorageValidationError) {
1054 // Validation errors will not clean the odex/vdex/art files but will mark
1055 // the file as non existent so that the PM knows it should purge it from its
1056 // records.
1057 LOG(INFO) << "ReconcileSecondaryStorageValidationError";
1058 reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_DE,
1059 /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ false);
1060 }
1061
TEST_F(ReconcileTest,ReconcileSecondaryAppOwnershipValidationError)1062 TEST_F(ReconcileTest, ReconcileSecondaryAppOwnershipValidationError) {
1063 LOG(INFO) << "ReconcileSecondaryAppOwnershipValidationError";
1064 // Attempt to reconcile the dex files of the test app from a different app.
1065 std::string another_app = "another.app";
1066 reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_CE,
1067 /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ false, kSystemUid, &another_app);
1068 }
1069
TEST_F(ReconcileTest,ReconcileSecondaryAcessViaDifferentUidError)1070 TEST_F(ReconcileTest, ReconcileSecondaryAcessViaDifferentUidError) {
1071 LOG(INFO) << "ReconcileSecondaryAcessViaDifferentUidError";
1072 reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_CE,
1073 /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ false, kSystemUid);
1074 }
1075
1076 class ProfileTest : public DexoptTest {
1077 protected:
1078 std::string cur_profile_;
1079 std::string ref_profile_;
1080 std::string snap_profile_;
1081
1082 static constexpr const char* kPrimaryProfile = "primary.prof";
1083
SetUp()1084 virtual void SetUp() {
1085 if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
1086 GTEST_SKIP() << "Skipping legacy dexopt tests when ART Service is enabled";
1087 }
1088
1089 DexoptTest::SetUp();
1090 cur_profile_ = create_current_profile_path(
1091 kTestUserId, package_name_, kPrimaryProfile, /*is_secondary_dex*/ false);
1092 ref_profile_ = create_reference_profile_path(package_name_, kPrimaryProfile,
1093 /*is_secondary_dex*/ false);
1094 snap_profile_ = create_snapshot_profile_path(package_name_, kPrimaryProfile);
1095 }
1096
SetupProfile(const std::string & path,uid_t uid,gid_t gid,mode_t mode,int32_t num_dex)1097 void SetupProfile(const std::string& path, uid_t uid, gid_t gid, mode_t mode,
1098 int32_t num_dex) {
1099 run_cmd("profman --generate-test-profile-seed=" + std::to_string(num_dex) +
1100 " --generate-test-profile-num-dex=" + std::to_string(num_dex) +
1101 " --generate-test-profile=" + path);
1102 ::chmod(path.c_str(), mode);
1103 ::chown(path.c_str(), uid, gid);
1104 }
1105
SetupProfiles(bool setup_ref)1106 void SetupProfiles(bool setup_ref) {
1107 SetupProfile(cur_profile_, kTestAppUid, kTestAppGid, 0600, 1);
1108 if (setup_ref) {
1109 SetupProfile(ref_profile_, kTestAppUid, kTestAppGid, 0600, 2);
1110 }
1111 }
1112
createProfileSnapshot(int32_t appid,const std::string & package_name,bool expected_result)1113 void createProfileSnapshot(int32_t appid, const std::string& package_name,
1114 bool expected_result) {
1115 bool result;
1116 ASSERT_BINDER_SUCCESS(service_->createProfileSnapshot(
1117 appid, package_name, kPrimaryProfile, apk_path_, &result));
1118 ASSERT_EQ(expected_result, result);
1119
1120 if (!expected_result) {
1121 // Do not check the files if we expect to fail.
1122 return;
1123 }
1124
1125 // Check that the snapshot was created with the expected access flags.
1126 CheckFileAccess(snap_profile_, kSystemUid, kSystemGid, 0600 | S_IFREG);
1127
1128 // The snapshot should be equivalent to the merge of profiles.
1129 std::string expected_profile_content = snap_profile_ + ".expected";
1130 run_cmd("rm -f " + expected_profile_content);
1131 run_cmd("touch " + expected_profile_content);
1132 // We force merging when creating the expected profile to make sure
1133 // that the random profiles do not affect the output.
1134 run_cmd("profman --force-merge --profile-file=" + cur_profile_ +
1135 " --profile-file=" + ref_profile_ +
1136 " --reference-profile-file=" + expected_profile_content +
1137 " --apk=" + apk_path_);
1138
1139 ASSERT_TRUE(AreFilesEqual(expected_profile_content, snap_profile_));
1140
1141 pid_t pid = fork();
1142 if (pid == 0) {
1143 /* child */
1144 TransitionToSystemServer();
1145
1146 // System server should be able to open the the spanshot.
1147 unique_fd fd(open(snap_profile_.c_str(), O_RDONLY));
1148 ASSERT_TRUE(fd > -1) << "Failed to open profile as kSystemUid: " << strerror(errno);
1149 _exit(0);
1150 }
1151 /* parent */
1152 ASSERT_TRUE(WIFEXITED(wait_child_with_timeout(pid, kTimeoutMs)));
1153 }
1154
mergePackageProfiles(const std::string & package_name,const std::string & code_path,int expected_result)1155 void mergePackageProfiles(const std::string& package_name,
1156 const std::string& code_path,
1157 int expected_result) {
1158 int result;
1159 ASSERT_BINDER_SUCCESS(service_->mergeProfiles(
1160 kTestAppUid, package_name, code_path, &result));
1161 ASSERT_EQ(expected_result, result);
1162
1163 // There's nothing to check if the files are empty.
1164 if (result == PROFILES_ANALYSIS_DONT_OPTIMIZE_EMPTY_PROFILES) {
1165 return;
1166 }
1167
1168 // Check that the snapshot was created with the expected access flags.
1169 CheckFileAccess(ref_profile_, kTestAppUid, kTestAppUid, 0640 | S_IFREG);
1170
1171 // The snapshot should be equivalent to the merge of profiles.
1172 std::string ref_profile_content = ref_profile_ + ".expected";
1173 run_cmd("rm -f " + ref_profile_content);
1174 run_cmd("touch " + ref_profile_content);
1175 run_cmd("profman --profile-file=" + cur_profile_ +
1176 " --profile-file=" + ref_profile_ +
1177 " --reference-profile-file=" + ref_profile_content);
1178
1179 ASSERT_TRUE(AreFilesEqual(ref_profile_content, ref_profile_));
1180 }
1181
preparePackageProfile(const std::string & package_name,const std::string & profile_name,bool has_dex_metadata,bool has_user_id,bool expected_result)1182 void preparePackageProfile(const std::string& package_name, const std::string& profile_name,
1183 bool has_dex_metadata, bool has_user_id, bool expected_result) {
1184 bool result;
1185 ASSERT_BINDER_SUCCESS(
1186 service_->prepareAppProfile(package_name, has_user_id ? kTestUserId : USER_NULL,
1187 kTestAppId, profile_name, apk_path_,
1188 has_dex_metadata ? std::make_optional<std::string>(
1189 dm_file_)
1190 : std::nullopt,
1191 &result));
1192 ASSERT_EQ(expected_result, result);
1193
1194 if (!expected_result) {
1195 // Do not check the files if we expect to fail.
1196 return;
1197 }
1198
1199 std::string code_path_cur_prof =
1200 create_current_profile_path(kTestUserId, package_name, profile_name,
1201 /*is_secondary_dex*/ false);
1202 std::string code_path_ref_profile =
1203 create_reference_profile_path(package_name, profile_name,
1204 /*is_secondary_dex*/ false);
1205
1206 if (has_user_id) {
1207 // Check that we created the current profile.
1208 CheckFileAccess(code_path_cur_prof, kTestAppUid, kTestAppUid, 0600 | S_IFREG);
1209 } else {
1210 // Without a user ID, we don't generate a current profile.
1211 ASSERT_EQ(-1, access(code_path_cur_prof.c_str(), R_OK));
1212 }
1213
1214 if (has_dex_metadata) {
1215 int32_t uid = has_user_id ? kTestAppUid : multiuser_get_uid(USER_SYSTEM, kTestAppId);
1216 // Check that we created the reference profile.
1217 CheckFileAccess(code_path_ref_profile, uid, uid, 0640 | S_IFREG);
1218 } else {
1219 // Without dex metadata, we don't generate a reference profile.
1220 ASSERT_EQ(-1, access(code_path_ref_profile.c_str(), R_OK));
1221 }
1222 }
1223
1224 protected:
TransitionToSystemServer()1225 void TransitionToSystemServer() {
1226 ASSERT_TRUE(DropCapabilities(kSystemUid, kSystemGid));
1227 int32_t res = selinux_android_setcon("u:r:system_server:s0");
1228 ASSERT_EQ(0, res) << "Failed to setcon " << strerror(errno);
1229 }
1230
AreFilesEqual(const std::string & file1,const std::string & file2)1231 bool AreFilesEqual(const std::string& file1, const std::string& file2) {
1232 std::vector<uint8_t> content1;
1233 std::vector<uint8_t> content2;
1234
1235 if (!ReadAll(file1, &content1)) return false;
1236 if (!ReadAll(file2, &content2)) return false;
1237 return content1 == content2;
1238 }
1239
ReadAll(const std::string & file,std::vector<uint8_t> * content)1240 bool ReadAll(const std::string& file, std::vector<uint8_t>* content) {
1241 unique_fd fd(open(file.c_str(), O_RDONLY));
1242 if (fd < 0) {
1243 PLOG(ERROR) << "Failed to open " << file;
1244 return false;
1245 }
1246 struct stat st;
1247 if (fstat(fd, &st) != 0) {
1248 PLOG(ERROR) << "Failed to stat " << file;
1249 return false;
1250 }
1251 content->resize(st.st_size);
1252 bool result = ReadFully(fd, content->data(), content->size());
1253 if (!result) {
1254 PLOG(ERROR) << "Failed to read " << file;
1255 }
1256 return result;
1257 }
1258 };
1259
TEST_F(ProfileTest,ProfileSnapshotOk)1260 TEST_F(ProfileTest, ProfileSnapshotOk) {
1261 LOG(INFO) << "ProfileSnapshotOk";
1262
1263 SetupProfiles(/*setup_ref*/ true);
1264 createProfileSnapshot(kTestAppId, package_name_, /*expected_result*/ true);
1265 }
1266
1267 // The reference profile is created on the fly. We need to be able to
1268 // snapshot without one.
TEST_F(ProfileTest,ProfileSnapshotOkNoReference)1269 TEST_F(ProfileTest, ProfileSnapshotOkNoReference) {
1270 LOG(INFO) << "ProfileSnapshotOkNoReference";
1271
1272 SetupProfiles(/*setup_ref*/ false);
1273 createProfileSnapshot(kTestAppId, package_name_, /*expected_result*/ true);
1274 }
1275
TEST_F(ProfileTest,ProfileSnapshotFailWrongPackage)1276 TEST_F(ProfileTest, ProfileSnapshotFailWrongPackage) {
1277 LOG(INFO) << "ProfileSnapshotFailWrongPackage";
1278
1279 SetupProfiles(/*setup_ref*/ true);
1280 createProfileSnapshot(kTestAppId, "not.there", /*expected_result*/ false);
1281 }
1282
TEST_F(ProfileTest,ProfileSnapshotDestroySnapshot)1283 TEST_F(ProfileTest, ProfileSnapshotDestroySnapshot) {
1284 LOG(INFO) << "ProfileSnapshotDestroySnapshot";
1285
1286 SetupProfiles(/*setup_ref*/ true);
1287 createProfileSnapshot(kTestAppId, package_name_, /*expected_result*/ true);
1288
1289 ASSERT_BINDER_SUCCESS(service_->destroyProfileSnapshot(package_name_, kPrimaryProfile));
1290 struct stat st;
1291 ASSERT_EQ(-1, stat(snap_profile_.c_str(), &st));
1292 ASSERT_EQ(ENOENT, errno);
1293 }
1294
TEST_F(ProfileTest,ProfileMergeOk)1295 TEST_F(ProfileTest, ProfileMergeOk) {
1296 LOG(INFO) << "ProfileMergeOk";
1297
1298 SetupProfiles(/*setup_ref*/ true);
1299 mergePackageProfiles(package_name_, "primary.prof", PROFILES_ANALYSIS_OPTIMIZE);
1300 }
1301
1302 // The reference profile is created on the fly. We need to be able to
1303 // merge without one.
TEST_F(ProfileTest,ProfileMergeOkNoReference)1304 TEST_F(ProfileTest, ProfileMergeOkNoReference) {
1305 LOG(INFO) << "ProfileMergeOkNoReference";
1306
1307 SetupProfiles(/*setup_ref*/ false);
1308 mergePackageProfiles(package_name_, "primary.prof", PROFILES_ANALYSIS_OPTIMIZE);
1309 }
1310
TEST_F(ProfileTest,ProfileMergeFailWrongPackage)1311 TEST_F(ProfileTest, ProfileMergeFailWrongPackage) {
1312 LOG(INFO) << "ProfileMergeFailWrongPackage";
1313
1314 SetupProfiles(/*setup_ref*/ true);
1315 mergePackageProfiles("not.there", "primary.prof",
1316 PROFILES_ANALYSIS_DONT_OPTIMIZE_EMPTY_PROFILES);
1317 }
1318
TEST_F(ProfileTest,ProfileDirOk)1319 TEST_F(ProfileTest, ProfileDirOk) {
1320 LOG(INFO) << "ProfileDirOk";
1321
1322 std::string cur_profile_dir = create_primary_current_profile_package_dir_path(
1323 kTestUserId, package_name_);
1324 std::string cur_profile_file = create_current_profile_path(kTestUserId, package_name_,
1325 kPrimaryProfile, /*is_secondary_dex*/false);
1326 std::string ref_profile_dir = create_primary_reference_profile_package_dir_path(package_name_);
1327
1328 CheckFileAccess(cur_profile_dir, kTestAppUid, kTestAppUid, 0700 | S_IFDIR);
1329 CheckFileAccess(ref_profile_dir, kSystemUid, kTestAppGid, 0770 | S_IFDIR);
1330 }
1331
1332 // Verify that the profile directories are fixed up during an upgrade.
1333 // (The reference profile directory is prepared lazily).
TEST_F(ProfileTest,ProfileDirOkAfterFixup)1334 TEST_F(ProfileTest, ProfileDirOkAfterFixup) {
1335 LOG(INFO) << "ProfileDirOkAfterFixup";
1336
1337 std::string cur_profile_dir = create_primary_current_profile_package_dir_path(
1338 kTestUserId, package_name_);
1339 std::string cur_profile_file = create_current_profile_path(kTestUserId, package_name_,
1340 kPrimaryProfile, /*is_secondary_dex*/false);
1341 std::string ref_profile_dir = create_primary_reference_profile_package_dir_path(package_name_);
1342
1343 // Simulate a pre-P setup by changing the owner to kTestAppGid and permissions to 0700.
1344 ASSERT_EQ(0, chown(ref_profile_dir.c_str(), kTestAppGid, kTestAppGid));
1345 ASSERT_EQ(0, chmod(ref_profile_dir.c_str(), 0700));
1346
1347 // Run createAppData again which will offer to fix-up the profile directories.
1348 ASSERT_BINDER_SUCCESS(service_->createAppData(volume_uuid_, package_name_, kTestUserId,
1349 kAppDataFlags, kTestAppUid, 0 /* previousAppId */,
1350 se_info_, kOSdkVersion, &ce_data_inode_,
1351 &de_data_inode_));
1352
1353 // Check the file access.
1354 CheckFileAccess(cur_profile_dir, kTestAppUid, kTestAppUid, 0700 | S_IFDIR);
1355 CheckFileAccess(ref_profile_dir, kSystemUid, kTestAppGid, 0770 | S_IFDIR);
1356 }
1357
TEST_F(ProfileTest,ProfilePrepareOk)1358 TEST_F(ProfileTest, ProfilePrepareOk) {
1359 LOG(INFO) << "ProfilePrepareOk";
1360 preparePackageProfile(package_name_, "split.prof", /*has_dex_metadata*/ true,
1361 /*has_user_id*/ true, /*expected_result*/ true);
1362 }
1363
TEST_F(ProfileTest,ProfilePrepareOkNoUser)1364 TEST_F(ProfileTest, ProfilePrepareOkNoUser) {
1365 LOG(INFO) << "ProfilePrepareOk";
1366 preparePackageProfile(package_name_, "split.prof", /*has_dex_metadata*/ true,
1367 /*has_user_id*/ false, /*expected_result*/ true);
1368 }
1369
TEST_F(ProfileTest,ProfilePrepareOkNoDm)1370 TEST_F(ProfileTest, ProfilePrepareOkNoDm) {
1371 LOG(INFO) << "ProfilePrepareOk";
1372 preparePackageProfile(package_name_, "split.prof", /*has_dex_metadata*/ false,
1373 /*has_user_id*/ true, /*expected_result*/ true);
1374 }
1375
TEST_F(ProfileTest,ProfilePrepareOkNoUserNoDm)1376 TEST_F(ProfileTest, ProfilePrepareOkNoUserNoDm) {
1377 LOG(INFO) << "ProfilePrepareOk";
1378 preparePackageProfile(package_name_, "split.prof", /*has_dex_metadata*/ false,
1379 /*has_user_id*/ false, /*expected_result*/ true);
1380 }
1381
TEST_F(ProfileTest,ProfilePrepareFailInvalidPackage)1382 TEST_F(ProfileTest, ProfilePrepareFailInvalidPackage) {
1383 LOG(INFO) << "ProfilePrepareFailInvalidPackage";
1384 preparePackageProfile("not.there.package", "split.prof", /*has_dex_metadata*/ true,
1385 /*has_user_id*/ true, /*expected_result*/ false);
1386 }
1387
TEST_F(ProfileTest,ProfilePrepareFailProfileChangedUid)1388 TEST_F(ProfileTest, ProfilePrepareFailProfileChangedUid) {
1389 LOG(INFO) << "ProfilePrepareFailProfileChangedUid";
1390 SetupProfiles(/*setup_ref*/ false);
1391 // Change the uid on the profile to trigger a failure.
1392 ::chown(cur_profile_.c_str(), kTestAppUid + 1, kTestAppGid + 1);
1393 preparePackageProfile(package_name_, "primary.prof", /*has_dex_metadata*/ true,
1394 /*has_user_id*/ true, /*expected_result*/ false);
1395 }
1396
TEST_F(ProfileTest,ClearAppProfilesOk)1397 TEST_F(ProfileTest, ClearAppProfilesOk) {
1398 LOG(INFO) << "ClearAppProfilesOk";
1399
1400 ASSERT_BINDER_SUCCESS(service_->clearAppProfiles(package_name_, "primary.prof"));
1401 ASSERT_BINDER_SUCCESS(service_->clearAppProfiles(package_name_, "image_editor.split.prof"));
1402 }
1403
TEST_F(ProfileTest,ClearAppProfilesFailWrongProfileName)1404 TEST_F(ProfileTest, ClearAppProfilesFailWrongProfileName) {
1405 LOG(INFO) << "ClearAppProfilesFailWrongProfileName";
1406
1407 ASSERT_BINDER_FAIL(
1408 service_->clearAppProfiles(package_name_,
1409 "../../../../dalvik-cache/arm64/"
1410 "system@app@[email protected]@classes.vdex"));
1411 ASSERT_BINDER_FAIL(service_->clearAppProfiles(package_name_, "image_editor.split.apk"));
1412 }
1413
TEST_F(ProfileTest,CopySystemProfileOk)1414 TEST_F(ProfileTest, CopySystemProfileOk) {
1415 LOG(INFO) << "CopySystemProfileOk";
1416
1417 bool result;
1418 ASSERT_BINDER_SUCCESS(
1419 service_->copySystemProfile("/data/app/random.string/package.name.random/base.apk.prof",
1420 kTestAppUid, package_name_, "primary.prof", &result));
1421 }
1422
TEST_F(ProfileTest,CopySystemProfileFailWrongSystemProfilePath)1423 TEST_F(ProfileTest, CopySystemProfileFailWrongSystemProfilePath) {
1424 LOG(INFO) << "CopySystemProfileFailWrongSystemProfilePath";
1425
1426 bool result;
1427 ASSERT_BINDER_FAIL(service_->copySystemProfile("../../secret.dat", kTestAppUid, package_name_,
1428 "primary.prof", &result));
1429 ASSERT_BINDER_FAIL(service_->copySystemProfile("/data/user/package.name/secret.data",
1430 kTestAppUid, package_name_, "primary.prof",
1431 &result));
1432 }
1433
TEST_F(ProfileTest,CopySystemProfileFailWrongProfileName)1434 TEST_F(ProfileTest, CopySystemProfileFailWrongProfileName) {
1435 LOG(INFO) << "CopySystemProfileFailWrongProfileName";
1436
1437 bool result;
1438 ASSERT_BINDER_FAIL(
1439 service_->copySystemProfile("/data/app/random.string/package.name.random/base.apk.prof",
1440 kTestAppUid, package_name_,
1441 "../../../../dalvik-cache/arm64/test.vdex", &result));
1442 ASSERT_BINDER_FAIL(
1443 service_->copySystemProfile("/data/app/random.string/package.name.random/base.apk.prof",
1444 kTestAppUid, package_name_, "/test.prof", &result));
1445 ASSERT_BINDER_FAIL(
1446 service_->copySystemProfile("/data/app/random.string/package.name.random/base.apk.prof",
1447 kTestAppUid, package_name_, "base.apk", &result));
1448 }
1449
1450 class BootProfileTest : public ProfileTest {
1451 public:
1452 std::vector<std::string> extra_apps_;
1453 std::vector<int64_t> extra_ce_data_inodes_;
1454
SetUp()1455 virtual void SetUp() {
1456 if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
1457 GTEST_SKIP() << "Skipping legacy dexopt tests when ART Service is enabled";
1458 }
1459
1460 ProfileTest::SetUp();
1461 intial_android_profiles_dir = android_profiles_dir;
1462 // Generate profiles for some extra apps.
1463 // When merging boot profile we split profiles into small groups to avoid
1464 // opening a lot of file descriptors at the same time.
1465 // (Currently the group size for aggregation is 10)
1466 //
1467 // To stress test that works fine, create profile for more apps.
1468 createAppProfilesForBootMerge(21);
1469 }
1470
TearDown()1471 virtual void TearDown() {
1472 if (base::GetBoolProperty("dalvik.vm.useartservice", false)) {
1473 GTEST_SKIP();
1474 }
1475
1476 android_profiles_dir = intial_android_profiles_dir;
1477 deleteAppProfilesForBootMerge();
1478 ProfileTest::TearDown();
1479 }
1480
createAppProfilesForBootMerge(size_t number_of_profiles)1481 void createAppProfilesForBootMerge(size_t number_of_profiles) {
1482 for (size_t i = 0; i < number_of_profiles; i++) {
1483 int64_t ce_data_inode;
1484 int64_t de_data_inode;
1485 std::string package_name = "dummy_test_pkg" + std::to_string(i);
1486 LOG(INFO) << package_name;
1487 ASSERT_BINDER_SUCCESS(
1488 service_->createAppData(volume_uuid_, package_name, kTestUserId, kAppDataFlags,
1489 kTestAppUid, 0 /* previousAppId */, se_info_,
1490 kOSdkVersion, &ce_data_inode, &de_data_inode));
1491 extra_apps_.push_back(package_name);
1492 extra_ce_data_inodes_.push_back(ce_data_inode);
1493 std::string profile = create_current_profile_path(
1494 kTestUserId, package_name, kPrimaryProfile, /*is_secondary_dex*/ false);
1495 SetupProfile(profile, kTestAppUid, kTestAppGid, 0600, 1);
1496 }
1497 }
1498
deleteAppProfilesForBootMerge()1499 void deleteAppProfilesForBootMerge() {
1500 if (kDebug) {
1501 return;
1502 }
1503 for (size_t i = 0; i < extra_apps_.size(); i++) {
1504 service_->destroyAppData(
1505 volume_uuid_, extra_apps_[i], kTestUserId, kAppDataFlags, extra_ce_data_inodes_[i]);
1506 }
1507 }
1508
UpdateAndroidProfilesDir(const std::string & profile_dir)1509 void UpdateAndroidProfilesDir(const std::string& profile_dir) {
1510 android_profiles_dir = profile_dir;
1511 // We need to create the reference profile directory in the new profile dir.
1512 run_cmd("mkdir -p " + profile_dir + "/ref");
1513 }
1514
createBootImageProfileSnapshot(const std::string & classpath,bool expected_result)1515 void createBootImageProfileSnapshot(const std::string& classpath, bool expected_result) {
1516 bool result;
1517 ASSERT_BINDER_SUCCESS(service_->createProfileSnapshot(
1518 -1, "android", "android.prof", classpath, &result));
1519 ASSERT_EQ(expected_result, result);
1520
1521 if (!expected_result) {
1522 // Do not check the files if we expect to fail.
1523 return;
1524 }
1525
1526 // Check that the snapshot was created with he expected access flags.
1527 const std::string boot_profile = create_snapshot_profile_path("android", "android.prof");
1528 CheckFileAccess(boot_profile, kSystemUid, kSystemGid, 0600 | S_IFREG);
1529
1530 pid_t pid = fork();
1531 if (pid == 0) {
1532 /* child */
1533 TransitionToSystemServer();
1534
1535 // System server should be able to open the snapshot.
1536 unique_fd fd(open(boot_profile.c_str(), O_RDONLY));
1537 ASSERT_TRUE(fd > -1) << "Failed to open profile as kSystemUid: " << strerror(errno);
1538 _exit(0);
1539 }
1540 /* parent */
1541 ASSERT_TRUE(WIFEXITED(wait_child_with_timeout(pid, kTimeoutMs)));
1542 }
1543 protected:
1544 std::string intial_android_profiles_dir;
1545 };
1546
TEST_F(BootProfileTest,BootProfileSnapshotOk)1547 TEST_F(BootProfileTest, BootProfileSnapshotOk) {
1548 LOG(INFO) << "BootProfileSnapshotOk";
1549 char* boot_classpath = getenv("BOOTCLASSPATH");
1550 ASSERT_TRUE(boot_classpath != nullptr);
1551 createBootImageProfileSnapshot(boot_classpath, /*expected_result*/ true);
1552 }
1553
TEST_F(BootProfileTest,BootProfileSnapshotFailEmptyClasspath)1554 TEST_F(BootProfileTest, BootProfileSnapshotFailEmptyClasspath) {
1555 LOG(INFO) << "BootProfileSnapshotFailEmptyClasspath";
1556
1557 createBootImageProfileSnapshot(/*boot_classpath*/ "", /*expected_result*/ false);
1558 }
1559
TEST_F(BootProfileTest,BootProfileSnapshotOkNoProfiles)1560 TEST_F(BootProfileTest, BootProfileSnapshotOkNoProfiles) {
1561 LOG(INFO) << "BootProfileSnapshotOkNoProfiles";
1562 char* boot_classpath = getenv("BOOTCLASSPATH");
1563 ASSERT_TRUE(boot_classpath != nullptr);
1564
1565 // The app_apk_dir has no profiles. So we shouldn't be able to merge anything.
1566 // Still, this is not a failure case.
1567 UpdateAndroidProfilesDir(app_apk_dir_);
1568 createBootImageProfileSnapshot(boot_classpath, /*expected_result*/ true);
1569 }
1570
1571 // Verify that profile collection.
TEST_F(BootProfileTest,CollectProfiles)1572 TEST_F(BootProfileTest, CollectProfiles) {
1573 LOG(INFO) << "CollectProfiles";
1574
1575 // Create some profile directories mimicking the real profile structure.
1576 run_cmd("mkdir -p " + app_private_dir_de_ + "/profiles/ref");
1577 run_cmd("mkdir -p " + app_private_dir_de_ + "/profiles/cur/0/");
1578 run_cmd("mkdir -p " + app_private_dir_de_ + "/profiles/cur/1/");
1579 // Create an empty profile.
1580 run_cmd("touch " + app_private_dir_de_ + "/profiles/cur/1/primary.prof");
1581 // Create a random file.
1582 run_cmd("touch " + app_private_dir_de_ + "/profiles/cur/0/non.profile.file");
1583
1584 // Create some non-empty profiles.
1585 std::string current_prof = app_private_dir_de_ + "/profiles/cur/0/primary.prof";
1586 run_cmd("echo 1 > " + current_prof);
1587 std::string ref_prof = app_private_dir_de_ + "/profiles/ref/primary.prof";
1588 run_cmd("echo 1 > " + ref_prof);
1589
1590 UpdateAndroidProfilesDir(app_private_dir_de_ + "/profiles");
1591
1592 std::vector<std::string> profiles;
1593 collect_profiles(&profiles);
1594
1595 // Only two profiles should be in the output.
1596 ASSERT_EQ(2u, profiles.size());
1597 ASSERT_TRUE(std::find(profiles.begin(), profiles.end(), current_prof) != profiles.end());
1598 ASSERT_TRUE(std::find(profiles.begin(), profiles.end(), ref_prof) != profiles.end());
1599 }
1600
TEST_F(DexoptTest,select_execution_binary)1601 TEST_F(DexoptTest, select_execution_binary) {
1602 LOG(INFO) << "DexoptTestselect_execution_binary";
1603
1604 std::string release_str = app_private_dir_ce_ + "/release";
1605 std::string debug_str = app_private_dir_ce_ + "/debug";
1606
1607 // Setup the binaries. Note that we only need executable files to actually
1608 // test the execution binary selection
1609 run_cmd("touch " + release_str);
1610 run_cmd("touch " + debug_str);
1611 run_cmd("chmod 777 " + release_str);
1612 run_cmd("chmod 777 " + debug_str);
1613
1614 const char* release = release_str.c_str();
1615 const char* debug = debug_str.c_str();
1616
1617 ASSERT_STREQ(release, select_execution_binary(
1618 release,
1619 debug,
1620 /*background_job_compile=*/ false,
1621 /*is_debug_runtime=*/ false,
1622 /*is_release=*/ false,
1623 /*is_debuggable_build=*/ false));
1624
1625 ASSERT_STREQ(release, select_execution_binary(
1626 release,
1627 debug,
1628 /*background_job_compile=*/ true,
1629 /*is_debug_runtime=*/ false,
1630 /*is_release=*/ true,
1631 /*is_debuggable_build=*/ true));
1632
1633 ASSERT_STREQ(debug, select_execution_binary(
1634 release,
1635 debug,
1636 /*background_job_compile=*/ false,
1637 /*is_debug_runtime=*/ true,
1638 /*is_release=*/ false,
1639 /*is_debuggable_build=*/ false));
1640
1641 ASSERT_STREQ(debug, select_execution_binary(
1642 release,
1643 debug,
1644 /*background_job_compile=*/ true,
1645 /*is_debug_runtime=*/ false,
1646 /*is_release=*/ false,
1647 /*is_debuggable_build=*/ true));
1648
1649
1650 // Select the release when the debug file is not there.
1651 ASSERT_STREQ(release, select_execution_binary(
1652 release,
1653 "does_not_exist",
1654 /*background_job_compile=*/ false,
1655 /*is_debug_runtime=*/ true,
1656 /*is_release=*/ false,
1657 /*is_debuggable_build=*/ false));
1658 }
1659
1660 } // namespace installd
1661 } // namespace android
1662