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/properties.h> 27 #include <android-base/scopeguard.h> 28 #include <android-base/stringprintf.h> 29 #include <android-base/unique_fd.h> 30 #include <binder/Status.h> 31 #include <cutils/properties.h> 32 33 #include <gtest/gtest.h> 34 35 #include <selinux/android.h> 36 #include <selinux/avc.h> 37 38 #include "binder_test_utils.h" 39 #include "dexopt.h" 40 #include "InstalldNativeService.h" 41 #include "globals.h" 42 #include "tests/test_utils.h" 43 #include "utils.h" 44 45 using android::base::ReadFully; 46 using android::base::unique_fd; 47 48 namespace android { 49 namespace installd { 50 51 // TODO(calin): try to dedup this code. 52 #if defined(__arm__) 53 static const std::string kRuntimeIsa = "arm"; 54 #elif defined(__aarch64__) 55 static const std::string kRuntimeIsa = "arm64"; 56 #elif defined(__mips__) && !defined(__LP64__) 57 static const std::string kRuntimeIsa = "mips"; 58 #elif defined(__mips__) && defined(__LP64__) 59 static const std::string kRuntimeIsa = "mips64"; 60 #elif defined(__i386__) 61 static const std::string kRuntimeIsa = "x86"; 62 #elif defined(__x86_64__) 63 static const std::string kRuntimeIsa = "x86_64"; 64 #else 65 static const std::string kRuntimeIsa = "none"; 66 #endif 67 68 int get_property(const char *key, char *value, const char *default_value) { 69 return property_get(key, value, default_value); 70 } 71 72 bool calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path, 73 const char *instruction_set) { 74 return calculate_oat_file_path_default(path, oat_dir, apk_path, instruction_set); 75 } 76 77 bool calculate_odex_file_path(char path[PKG_PATH_MAX], const char *apk_path, 78 const char *instruction_set) { 79 return calculate_odex_file_path_default(path, apk_path, instruction_set); 80 } 81 82 bool create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *instruction_set) { 83 return create_cache_path_default(path, src, instruction_set); 84 } 85 86 static void run_cmd(const std::string& cmd) { 87 system(cmd.c_str()); 88 } 89 90 template <typename Visitor> 91 static void run_cmd_and_process_output(const std::string& cmd, const Visitor& visitor) { 92 FILE* file = popen(cmd.c_str(), "r"); 93 CHECK(file != nullptr) << "Failed to ptrace " << cmd; 94 char* line = nullptr; 95 while (true) { 96 size_t n = 0u; 97 ssize_t value = getline(&line, &n, file); 98 if (value == -1) { 99 break; 100 } 101 visitor(line); 102 } 103 free(line); 104 fclose(file); 105 } 106 107 static int mkdir(const std::string& path, uid_t owner, gid_t group, mode_t mode) { 108 int ret = ::mkdir(path.c_str(), mode); 109 if (ret != 0) { 110 return ret; 111 } 112 ret = ::chown(path.c_str(), owner, group); 113 if (ret != 0) { 114 return ret; 115 } 116 return ::chmod(path.c_str(), mode); 117 } 118 119 static int log_callback(int type, const char *fmt, ...) { // NOLINT 120 va_list ap; 121 int priority; 122 123 switch (type) { 124 case SELINUX_WARNING: 125 priority = ANDROID_LOG_WARN; 126 break; 127 case SELINUX_INFO: 128 priority = ANDROID_LOG_INFO; 129 break; 130 default: 131 priority = ANDROID_LOG_ERROR; 132 break; 133 } 134 va_start(ap, fmt); 135 LOG_PRI_VA(priority, "SELinux", fmt, ap); 136 va_end(ap); 137 return 0; 138 } 139 140 static bool init_selinux() { 141 int selinux_enabled = (is_selinux_enabled() > 0); 142 143 union selinux_callback cb; 144 cb.func_log = log_callback; 145 selinux_set_callback(SELINUX_CB_LOG, cb); 146 147 if (selinux_enabled && selinux_status_open(true) < 0) { 148 LOG(ERROR) << "Could not open selinux status; exiting"; 149 return false; 150 } 151 152 return true; 153 } 154 155 // Base64 encoding of a simple dex files with 2 methods. 156 static const char kDexFile[] = 157 "UEsDBBQAAAAIAOiOYUs9y6BLCgEAABQCAAALABwAY2xhc3Nlcy5kZXhVVAkAA/Ns+lkOHv1ZdXgL" 158 "AAEEI+UCAASIEwAAS0mt4DIwNmX4qpn7j/2wA7v7N+ZvoQpCJRlVx5SWa4YaiDAxMBQwMDBUhJkI" 159 "MUBBDyMDAzsDRJwFxAdioBDDHAYEYAbiFUAM1M5wAIhFGCGKDIDYAogdgNgDiH2BOAiI0xghekDm" 160 "sQIxGxQzM6ACRijNhCbOhCZfyohdPYyuh8szgtVkMkLsLhAAqeCDi+ejibPZZOZlltgxsDnqZSWW" 161 "JTKwOUFoZh9HayDhZM0g5AMS0M9JzEvX90/KSk0usWZgDAMaws5nAyXBzmpoYGlgAjsAyJoBMp0b" 162 "zQ8gGhbOTEhhzYwU3qxIYc2GFN6MClC/AhUyKUDMAYU9M1Qc5F8GKBscVgIQM0FxCwBQSwECHgMU" 163 "AAAACADojmFLPcugSwoBAAAUAgAACwAYAAAAAAAAAAAAoIEAAAAAY2xhc3Nlcy5kZXhVVAUAA/Ns" 164 "+ll1eAsAAQQj5QIABIgTAABQSwUGAAAAAAEAAQBRAAAATwEAAAAA"; 165 166 class DexoptTestEnvTest : public testing::Test { 167 }; 168 169 TEST_F(DexoptTestEnvTest, CheckSelinux) { 170 ASSERT_EQ(1, is_selinux_enabled()); 171 172 // Crude cutout for virtual devices. 173 #if !defined(__i386__) && !defined(__x86_64__) 174 constexpr bool kIsX86 = false; 175 #else 176 constexpr bool kIsX86 = true; 177 #endif 178 ASSERT_TRUE(1 == security_getenforce() || kIsX86 || true /* b/119032200 */); 179 } 180 181 class DexoptTest : public testing::Test { 182 protected: 183 static constexpr bool kDebug = false; 184 static constexpr uid_t kSystemUid = 1000; 185 static constexpr uid_t kSystemGid = 1000; 186 static constexpr int32_t kOSdkVersion = 25; 187 static constexpr int32_t kAppDataFlags = FLAG_STORAGE_CE | FLAG_STORAGE_DE; 188 static constexpr int32_t kTestUserId = 0; 189 static constexpr uid_t kTestAppId = 19999; 190 191 const gid_t kTestAppUid = multiuser_get_uid(kTestUserId, kTestAppId); 192 const uid_t kTestAppGid = multiuser_get_shared_gid(kTestUserId, kTestAppId); 193 194 InstalldNativeService* service_; 195 std::unique_ptr<std::string> volume_uuid_; 196 std::string package_name_; 197 std::string apk_path_; 198 std::string app_apk_dir_; 199 std::string app_private_dir_ce_; 200 std::string app_private_dir_de_; 201 std::string se_info_; 202 std::string app_oat_dir_; 203 204 int64_t ce_data_inode_; 205 206 std::string secondary_dex_ce_; 207 std::string secondary_dex_ce_link_; 208 std::string secondary_dex_de_; 209 210 virtual void SetUp() { 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_ = nullptr; 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 230 virtual void TearDown() { 231 if (!kDebug) { 232 service_->destroyAppData( 233 volume_uuid_, package_name_, kTestUserId, kAppDataFlags, ce_data_inode_); 234 run_cmd("rm -rf " + app_apk_dir_); 235 run_cmd("rm -rf " + app_private_dir_ce_); 236 run_cmd("rm -rf " + app_private_dir_de_); 237 } 238 delete service_; 239 } 240 241 ::testing::AssertionResult create_mock_app() { 242 // Create the oat dir. 243 app_oat_dir_ = app_apk_dir_ + "/oat"; 244 // For debug mode, the directory might already exist. Avoid erroring out. 245 if (mkdir(app_apk_dir_, kSystemUid, kSystemGid, 0755) != 0 && !kDebug) { 246 return ::testing::AssertionFailure() << "Could not create app dir " << app_apk_dir_ 247 << " : " << strerror(errno); 248 } 249 binder::Status status = service_->createOatDir(app_oat_dir_, kRuntimeIsa); 250 if (!status.isOk()) { 251 return ::testing::AssertionFailure() << "Could not create oat dir: " 252 << status.toString8().c_str(); 253 } 254 255 // Copy the primary apk. 256 apk_path_ = app_apk_dir_ + "/base.jar"; 257 std::string error_msg; 258 if (!WriteBase64ToFile(kDexFile, apk_path_, kSystemUid, kSystemGid, 0644, &error_msg)) { 259 return ::testing::AssertionFailure() << "Could not write base64 file to " << apk_path_ 260 << " : " << error_msg; 261 } 262 263 // Create the app user data. 264 status = service_->createAppData( 265 volume_uuid_, 266 package_name_, 267 kTestUserId, 268 kAppDataFlags, 269 kTestAppUid, 270 se_info_, 271 kOSdkVersion, 272 &ce_data_inode_); 273 if (!status.isOk()) { 274 return ::testing::AssertionFailure() << "Could not create app data: " 275 << status.toString8().c_str(); 276 } 277 278 // Create a secondary dex file on CE storage 279 const char* volume_uuid_cstr = volume_uuid_ == nullptr ? nullptr : volume_uuid_->c_str(); 280 app_private_dir_ce_ = create_data_user_ce_package_path( 281 volume_uuid_cstr, kTestUserId, package_name_.c_str()); 282 secondary_dex_ce_ = app_private_dir_ce_ + "/secondary_ce.jar"; 283 if (!WriteBase64ToFile(kDexFile, 284 secondary_dex_ce_, 285 kTestAppUid, 286 kTestAppGid, 287 0600, 288 &error_msg)) { 289 return ::testing::AssertionFailure() << "Could not write base64 file to " 290 << secondary_dex_ce_ << " : " << error_msg; 291 } 292 std::string app_private_dir_ce_link = create_data_user_ce_package_path_as_user_link( 293 volume_uuid_cstr, kTestUserId, package_name_.c_str()); 294 secondary_dex_ce_link_ = app_private_dir_ce_link + "/secondary_ce.jar"; 295 296 // Create a secondary dex file on DE storage. 297 app_private_dir_de_ = create_data_user_de_package_path( 298 volume_uuid_cstr, kTestUserId, package_name_.c_str()); 299 secondary_dex_de_ = app_private_dir_de_ + "/secondary_de.jar"; 300 if (!WriteBase64ToFile(kDexFile, 301 secondary_dex_de_, 302 kTestAppUid, 303 kTestAppGid, 304 0600, 305 &error_msg)) { 306 return ::testing::AssertionFailure() << "Could not write base64 file to " 307 << secondary_dex_de_ << " : " << error_msg; 308 } 309 310 // Fix app data uid. 311 status = service_->fixupAppData(volume_uuid_, kTestUserId); 312 if (!status.isOk()) { 313 return ::testing::AssertionFailure() << "Could not fixup app data: " 314 << status.toString8().c_str(); 315 } 316 317 return ::testing::AssertionSuccess(); 318 } 319 320 321 std::string GetSecondaryDexArtifact(const std::string& path, const std::string& type) { 322 std::string::size_type end = path.rfind('.'); 323 std::string::size_type start = path.rfind('/', end); 324 return path.substr(0, start) + "/oat/" + kRuntimeIsa + "/" + 325 path.substr(start + 1, end - start) + type; 326 } 327 328 void CompileSecondaryDex(const std::string& path, int32_t dex_storage_flag, 329 bool should_binder_call_succeed, bool should_dex_be_compiled = true, 330 /*out */ binder::Status* binder_result = nullptr, int32_t uid = -1, 331 const char* class_loader_context = nullptr) { 332 if (uid == -1) { 333 uid = kTestAppUid; 334 } 335 if (class_loader_context == nullptr) { 336 class_loader_context = "&"; 337 } 338 std::unique_ptr<std::string> package_name_ptr(new std::string(package_name_)); 339 int32_t dexopt_needed = 0; // does not matter; 340 std::unique_ptr<std::string> out_path = nullptr; // does not matter 341 int32_t dex_flags = DEXOPT_SECONDARY_DEX | dex_storage_flag; 342 std::string compiler_filter = "speed-profile"; 343 std::unique_ptr<std::string> class_loader_context_ptr( 344 new std::string(class_loader_context)); 345 std::unique_ptr<std::string> se_info_ptr(new std::string(se_info_)); 346 bool downgrade = false; 347 int32_t target_sdk_version = 0; // default 348 std::unique_ptr<std::string> profile_name_ptr = nullptr; 349 std::unique_ptr<std::string> dm_path_ptr = nullptr; 350 std::unique_ptr<std::string> compilation_reason_ptr = nullptr; 351 352 binder::Status result = service_->dexopt(path, 353 uid, 354 package_name_ptr, 355 kRuntimeIsa, 356 dexopt_needed, 357 out_path, 358 dex_flags, 359 compiler_filter, 360 volume_uuid_, 361 class_loader_context_ptr, 362 se_info_ptr, 363 downgrade, 364 target_sdk_version, 365 profile_name_ptr, 366 dm_path_ptr, 367 compilation_reason_ptr); 368 ASSERT_EQ(should_binder_call_succeed, result.isOk()) << result.toString8().c_str(); 369 int expected_access = should_dex_be_compiled ? 0 : -1; 370 std::string odex = GetSecondaryDexArtifact(path, "odex"); 371 std::string vdex = GetSecondaryDexArtifact(path, "vdex"); 372 std::string art = GetSecondaryDexArtifact(path, "art"); 373 ASSERT_EQ(expected_access, access(odex.c_str(), R_OK)); 374 ASSERT_EQ(expected_access, access(vdex.c_str(), R_OK)); 375 ASSERT_EQ(-1, access(art.c_str(), R_OK)); // empty profiles do not generate an image. 376 if (binder_result != nullptr) { 377 *binder_result = result; 378 } 379 } 380 381 void reconcile_secondary_dex(const std::string& path, int32_t storage_flag, 382 bool should_binder_call_succeed, bool should_dex_exist, bool should_dex_be_deleted, 383 int32_t uid = -1, std::string* package_override = nullptr) { 384 if (uid == -1) { 385 uid = kTestAppUid; 386 } 387 std::vector<std::string> isas; 388 isas.push_back(kRuntimeIsa); 389 bool out_secondary_dex_exists = false; 390 binder::Status result = service_->reconcileSecondaryDexFile( 391 path, 392 package_override == nullptr ? package_name_ : *package_override, 393 uid, 394 isas, 395 volume_uuid_, 396 storage_flag, 397 &out_secondary_dex_exists); 398 399 ASSERT_EQ(should_binder_call_succeed, result.isOk()) << result.toString8().c_str(); 400 ASSERT_EQ(should_dex_exist, out_secondary_dex_exists); 401 402 int expected_access = should_dex_be_deleted ? -1 : 0; 403 std::string odex = GetSecondaryDexArtifact(path, "odex"); 404 std::string vdex = GetSecondaryDexArtifact(path, "vdex"); 405 std::string art = GetSecondaryDexArtifact(path, "art"); 406 ASSERT_EQ(expected_access, access(odex.c_str(), F_OK)); 407 ASSERT_EQ(expected_access, access(vdex.c_str(), F_OK)); 408 ASSERT_EQ(-1, access(art.c_str(), R_OK)); // empty profiles do not generate an image. 409 } 410 411 void CheckFileAccess(const std::string& file, uid_t uid, gid_t gid, mode_t mode) { 412 struct stat st; 413 ASSERT_EQ(0, stat(file.c_str(), &st)); 414 ASSERT_EQ(uid, st.st_uid); 415 ASSERT_EQ(gid, st.st_gid); 416 ASSERT_EQ(mode, st.st_mode); 417 } 418 419 void CompilePrimaryDexOk(std::string compiler_filter, 420 int32_t dex_flags, 421 const char* oat_dir, 422 int32_t uid, 423 int32_t dexopt_needed, 424 binder::Status* binder_result = nullptr, 425 const char* dm_path = nullptr, 426 bool downgrade = false) { 427 CompilePrimaryDex(compiler_filter, 428 dex_flags, 429 oat_dir, 430 uid, 431 dexopt_needed, 432 dm_path, 433 downgrade, 434 true, 435 binder_result); 436 } 437 438 void CompilePrimaryDexFail(std::string compiler_filter, 439 int32_t dex_flags, 440 const char* oat_dir, 441 int32_t uid, 442 int32_t dexopt_needed, 443 binder::Status* binder_result = nullptr, 444 const char* dm_path = nullptr, 445 bool downgrade = false) { 446 CompilePrimaryDex(compiler_filter, 447 dex_flags, 448 oat_dir, 449 uid, 450 dexopt_needed, 451 dm_path, 452 downgrade, 453 false, 454 binder_result); 455 } 456 457 void CompilePrimaryDex(std::string compiler_filter, 458 int32_t dex_flags, 459 const char* oat_dir, 460 int32_t uid, 461 int32_t dexopt_needed, 462 const char* dm_path, 463 bool downgrade, 464 bool should_binder_call_succeed, 465 /*out */ binder::Status* binder_result) { 466 std::unique_ptr<std::string> package_name_ptr(new std::string(package_name_)); 467 std::unique_ptr<std::string> out_path( 468 oat_dir == nullptr ? nullptr : new std::string(oat_dir)); 469 std::unique_ptr<std::string> class_loader_context_ptr(new std::string("&")); 470 std::unique_ptr<std::string> se_info_ptr(new std::string(se_info_)); 471 int32_t target_sdk_version = 0; // default 472 std::unique_ptr<std::string> profile_name_ptr(new std::string("primary.prof")); 473 std::unique_ptr<std::string> dm_path_ptr = nullptr; 474 if (dm_path != nullptr) { 475 dm_path_ptr.reset(new std::string(dm_path)); 476 } 477 std::unique_ptr<std::string> compilation_reason_ptr(new std::string("test-reason")); 478 479 bool prof_result; 480 ASSERT_BINDER_SUCCESS(service_->prepareAppProfile( 481 package_name_, kTestUserId, kTestAppId, *profile_name_ptr, apk_path_, 482 /*dex_metadata*/ nullptr, &prof_result)); 483 ASSERT_TRUE(prof_result); 484 485 binder::Status result = service_->dexopt(apk_path_, 486 uid, 487 package_name_ptr, 488 kRuntimeIsa, 489 dexopt_needed, 490 out_path, 491 dex_flags, 492 compiler_filter, 493 volume_uuid_, 494 class_loader_context_ptr, 495 se_info_ptr, 496 downgrade, 497 target_sdk_version, 498 profile_name_ptr, 499 dm_path_ptr, 500 compilation_reason_ptr); 501 ASSERT_EQ(should_binder_call_succeed, result.isOk()) << result.toString8().c_str(); 502 503 if (!should_binder_call_succeed) { 504 if (binder_result != nullptr) { 505 *binder_result = result; 506 } 507 return; 508 } 509 // Check the access to the compiler output. 510 // - speed-profile artifacts are not world-wide readable. 511 // - files are owned by the system uid. 512 std::string odex = GetPrimaryDexArtifact(oat_dir, apk_path_, "odex"); 513 std::string vdex = GetPrimaryDexArtifact(oat_dir, apk_path_, "vdex"); 514 std::string art = GetPrimaryDexArtifact(oat_dir, apk_path_, "art"); 515 516 bool is_public = (dex_flags & DEXOPT_PUBLIC) != 0; 517 mode_t mode = S_IFREG | (is_public ? 0644 : 0640); 518 CheckFileAccess(odex, kSystemUid, uid, mode); 519 CheckFileAccess(vdex, kSystemUid, uid, mode); 520 521 if (compiler_filter == "speed-profile") { 522 CheckFileAccess(art, kSystemUid, uid, mode); 523 } 524 if (binder_result != nullptr) { 525 *binder_result = result; 526 } 527 } 528 529 std::string GetPrimaryDexArtifact(const char* oat_dir, 530 const std::string& dex_path, 531 const std::string& type) { 532 if (oat_dir == nullptr) { 533 std::string path = dex_path; 534 for (auto it = path.begin() + 1; it < path.end(); ++it) { 535 if (*it == '/') { 536 *it = '@'; 537 } 538 } 539 return android_data_dir + DALVIK_CACHE + '/' + kRuntimeIsa + "/" + path 540 + "@classes.dex"; 541 } else { 542 std::string::size_type name_end = dex_path.rfind('.'); 543 std::string::size_type name_start = dex_path.rfind('/'); 544 return std::string(oat_dir) + "/" + kRuntimeIsa + "/" + 545 dex_path.substr(name_start + 1, name_end - name_start) + type; 546 } 547 } 548 }; 549 550 551 TEST_F(DexoptTest, DexoptSecondaryCe) { 552 LOG(INFO) << "DexoptSecondaryCe"; 553 CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE, 554 /*binder_ok*/ true, /*compile_ok*/ true); 555 } 556 557 TEST_F(DexoptTest, DexoptSecondaryCeLink) { 558 LOG(INFO) << "DexoptSecondaryCeLink"; 559 CompileSecondaryDex(secondary_dex_ce_link_, DEXOPT_STORAGE_CE, 560 /*binder_ok*/ true, /*compile_ok*/ true); 561 } 562 563 TEST_F(DexoptTest, DexoptSecondaryCeWithContext) { 564 LOG(INFO) << "DexoptSecondaryCeWithContext"; 565 std::string class_loader_context = "PCL[" + secondary_dex_ce_ + "]"; 566 CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE, 567 /*binder_ok*/ true, /*compile_ok*/ true, nullptr, -1, class_loader_context.c_str()); 568 } 569 570 TEST_F(DexoptTest, DexoptSecondaryDe) { 571 LOG(INFO) << "DexoptSecondaryDe"; 572 CompileSecondaryDex(secondary_dex_de_, DEXOPT_STORAGE_DE, 573 /*binder_ok*/ true, /*compile_ok*/ true); 574 } 575 576 TEST_F(DexoptTest, DexoptSecondaryDeWithContext) { 577 LOG(INFO) << "DexoptSecondaryDeWithContext"; 578 std::string class_loader_context = "PCL[" + secondary_dex_de_ + "]"; 579 CompileSecondaryDex(secondary_dex_de_, DEXOPT_STORAGE_DE, 580 /*binder_ok*/ true, /*compile_ok*/ true, nullptr, -1, class_loader_context.c_str()); 581 } 582 583 TEST_F(DexoptTest, DexoptSecondaryDoesNotExist) { 584 LOG(INFO) << "DexoptSecondaryDoesNotExist"; 585 // If the file validates but does not exist we do not treat it as an error. 586 binder::Status status; 587 CompileSecondaryDex(secondary_dex_ce_ + "not.there", DEXOPT_STORAGE_CE, 588 /*binder_ok*/ true, /*compile_ok*/ false, &status); 589 EXPECT_STREQ(status.toString8().c_str(), "No error"); 590 } 591 592 TEST_F(DexoptTest, DexoptSecondaryStorageValidationError) { 593 LOG(INFO) << "DexoptSecondaryStorageValidationError"; 594 binder::Status status; 595 CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_DE, 596 /*binder_ok*/ false, /*compile_ok*/ false, &status); 597 EXPECT_STREQ(status.toString8().c_str(), 598 "Status(-8, EX_SERVICE_SPECIFIC): '-1: Dexoptanalyzer path validation failed'"); 599 } 600 601 TEST_F(DexoptTest, DexoptSecondaryAppOwnershipValidationError) { 602 LOG(INFO) << "DexoptSecondaryAppOwnershipValidationError"; 603 binder::Status status; 604 CompileSecondaryDex("/data/data/random.app/secondary.jar", DEXOPT_STORAGE_CE, 605 /*binder_ok*/ false, /*compile_ok*/ false, &status); 606 EXPECT_STREQ(status.toString8().c_str(), 607 "Status(-8, EX_SERVICE_SPECIFIC): '-1: Dexoptanalyzer path validation failed'"); 608 } 609 610 TEST_F(DexoptTest, DexoptSecondaryAcessViaDifferentUidError) { 611 LOG(INFO) << "DexoptSecondaryAcessViaDifferentUidError"; 612 binder::Status status; 613 CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE, 614 /*binder_ok*/ false, /*compile_ok*/ false, &status, kSystemUid); 615 EXPECT_STREQ(status.toString8().c_str(), 616 "Status(-8, EX_SERVICE_SPECIFIC): '-1: Dexoptanalyzer open zip failed'"); 617 } 618 619 TEST_F(DexoptTest, DexoptPrimaryPublic) { 620 LOG(INFO) << "DexoptPrimaryPublic"; 621 CompilePrimaryDexOk("verify", 622 DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC, 623 app_oat_dir_.c_str(), 624 kTestAppGid, 625 DEX2OAT_FROM_SCRATCH); 626 } 627 628 TEST_F(DexoptTest, DexoptPrimaryFailedInvalidFilter) { 629 LOG(INFO) << "DexoptPrimaryFailedInvalidFilter"; 630 binder::Status status; 631 CompilePrimaryDexFail("awesome-filter", 632 DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PUBLIC, 633 app_oat_dir_.c_str(), 634 kTestAppGid, 635 DEX2OAT_FROM_SCRATCH, 636 &status); 637 EXPECT_STREQ(status.toString8().c_str(), 638 "Status(-8, EX_SERVICE_SPECIFIC): \'256: Dex2oat invocation for " 639 "/data/app/com.installd.test.dexopt/base.jar failed: unspecified dex2oat error'"); 640 } 641 642 TEST_F(DexoptTest, DexoptPrimaryProfileNonPublic) { 643 LOG(INFO) << "DexoptPrimaryProfileNonPublic"; 644 CompilePrimaryDexOk("speed-profile", 645 DEXOPT_BOOTCOMPLETE | DEXOPT_PROFILE_GUIDED | DEXOPT_GENERATE_APP_IMAGE, 646 app_oat_dir_.c_str(), 647 kTestAppGid, 648 DEX2OAT_FROM_SCRATCH); 649 } 650 651 TEST_F(DexoptTest, DexoptPrimaryProfilePublic) { 652 LOG(INFO) << "DexoptPrimaryProfilePublic"; 653 CompilePrimaryDexOk("speed-profile", 654 DEXOPT_BOOTCOMPLETE | DEXOPT_PROFILE_GUIDED | DEXOPT_PUBLIC | 655 DEXOPT_GENERATE_APP_IMAGE, 656 app_oat_dir_.c_str(), 657 kTestAppGid, 658 DEX2OAT_FROM_SCRATCH); 659 } 660 661 TEST_F(DexoptTest, DexoptPrimaryBackgroundOk) { 662 LOG(INFO) << "DexoptPrimaryBackgroundOk"; 663 CompilePrimaryDexOk("speed-profile", 664 DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PROFILE_GUIDED | 665 DEXOPT_GENERATE_APP_IMAGE, 666 app_oat_dir_.c_str(), 667 kTestAppGid, 668 DEX2OAT_FROM_SCRATCH); 669 } 670 671 TEST_F(DexoptTest, ResolveStartupConstStrings) { 672 LOG(INFO) << "DexoptDex2oatResolveStartupStrings"; 673 const std::string property = "persist.device_config.runtime.dex2oat_resolve_startup_strings"; 674 const std::string previous_value = android::base::GetProperty(property, ""); 675 auto restore_property = android::base::make_scope_guard([=]() { 676 android::base::SetProperty(property, previous_value); 677 }); 678 std::string odex = GetPrimaryDexArtifact(app_oat_dir_.c_str(), apk_path_, "odex"); 679 // Disable the property to start. 680 bool found_disable = false; 681 ASSERT_TRUE(android::base::SetProperty(property, "false")) << property; 682 CompilePrimaryDexOk("speed-profile", 683 DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PROFILE_GUIDED | 684 DEXOPT_GENERATE_APP_IMAGE, 685 app_oat_dir_.c_str(), 686 kTestAppGid, 687 DEX2OAT_FROM_SCRATCH); 688 run_cmd_and_process_output( 689 "oatdump --header-only --oat-file=" + odex, 690 [&](const std::string& line) { 691 if (line.find("--resolve-startup-const-strings=false") != std::string::npos) { 692 found_disable = true; 693 } 694 }); 695 EXPECT_TRUE(found_disable); 696 // Enable the property and inspect that .art artifact is larger. 697 bool found_enable = false; 698 ASSERT_TRUE(android::base::SetProperty(property, "true")) << property; 699 CompilePrimaryDexOk("speed-profile", 700 DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PROFILE_GUIDED | 701 DEXOPT_GENERATE_APP_IMAGE, 702 app_oat_dir_.c_str(), 703 kTestAppGid, 704 DEX2OAT_FROM_SCRATCH); 705 run_cmd_and_process_output( 706 "oatdump --header-only --oat-file=" + odex, 707 [&](const std::string& line) { 708 if (line.find("--resolve-startup-const-strings=true") != std::string::npos) { 709 found_enable = true; 710 } 711 }); 712 EXPECT_TRUE(found_enable); 713 } 714 715 class PrimaryDexReCompilationTest : public DexoptTest { 716 public: 717 virtual void SetUp() { 718 DexoptTest::SetUp(); 719 CompilePrimaryDexOk("verify", 720 DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC, 721 app_oat_dir_.c_str(), 722 kTestAppGid, 723 DEX2OAT_FROM_SCRATCH); 724 std::string odex = GetSecondaryDexArtifact(apk_path_, "odex"); 725 std::string vdex = GetSecondaryDexArtifact(apk_path_, "vdex"); 726 727 first_compilation_odex_fd_.reset(open(odex.c_str(), O_RDONLY)); 728 first_compilation_vdex_fd_.reset(open(vdex.c_str(), O_RDONLY)); 729 } 730 731 virtual void TearDown() { 732 first_compilation_odex_fd_.reset(-1); 733 first_compilation_vdex_fd_.reset(-1); 734 DexoptTest::TearDown(); 735 } 736 737 protected: 738 unique_fd first_compilation_odex_fd_; 739 unique_fd first_compilation_vdex_fd_; 740 }; 741 742 TEST_F(PrimaryDexReCompilationTest, DexoptPrimaryUpdateInPlaceVdex) { 743 LOG(INFO) << "DexoptPrimaryUpdateInPlaceVdex"; 744 745 CompilePrimaryDexOk("verify", 746 DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PUBLIC, 747 app_oat_dir_.c_str(), 748 kTestAppGid, 749 DEX2OAT_FOR_BOOT_IMAGE); 750 } 751 752 class ReconcileTest : public DexoptTest { 753 virtual void SetUp() { 754 DexoptTest::SetUp(); 755 CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE, 756 /*binder_ok*/ true, /*compile_ok*/ true); 757 CompileSecondaryDex(secondary_dex_de_, DEXOPT_STORAGE_DE, 758 /*binder_ok*/ true, /*compile_ok*/ true); 759 } 760 }; 761 762 TEST_F(ReconcileTest, ReconcileSecondaryCeExists) { 763 LOG(INFO) << "ReconcileSecondaryCeExists"; 764 reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_CE, 765 /*binder_ok*/ true, /*dex_ok */ true, /*odex_deleted*/ false); 766 } 767 768 TEST_F(ReconcileTest, ReconcileSecondaryCeLinkExists) { 769 LOG(INFO) << "ReconcileSecondaryCeLinkExists"; 770 reconcile_secondary_dex(secondary_dex_ce_link_, FLAG_STORAGE_CE, 771 /*binder_ok*/ true, /*dex_ok */ true, /*odex_deleted*/ false); 772 } 773 774 TEST_F(ReconcileTest, ReconcileSecondaryDeExists) { 775 LOG(INFO) << "ReconcileSecondaryDeExists"; 776 reconcile_secondary_dex(secondary_dex_de_, FLAG_STORAGE_DE, 777 /*binder_ok*/ true, /*dex_ok */ true, /*odex_deleted*/ false); 778 } 779 780 TEST_F(ReconcileTest, ReconcileSecondaryDeDoesNotExist) { 781 LOG(INFO) << "ReconcileSecondaryDeDoesNotExist"; 782 run_cmd("rm -rf " + secondary_dex_de_); 783 reconcile_secondary_dex(secondary_dex_de_, FLAG_STORAGE_DE, 784 /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ true); 785 } 786 787 TEST_F(ReconcileTest, ReconcileSecondaryStorageValidationError) { 788 // Validation errors will not clean the odex/vdex/art files but will mark 789 // the file as non existent so that the PM knows it should purge it from its 790 // records. 791 LOG(INFO) << "ReconcileSecondaryStorageValidationError"; 792 reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_DE, 793 /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ false); 794 } 795 796 TEST_F(ReconcileTest, ReconcileSecondaryAppOwnershipValidationError) { 797 LOG(INFO) << "ReconcileSecondaryAppOwnershipValidationError"; 798 // Attempt to reconcile the dex files of the test app from a different app. 799 std::string another_app = "another.app"; 800 reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_CE, 801 /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ false, kSystemUid, &another_app); 802 } 803 804 TEST_F(ReconcileTest, ReconcileSecondaryAcessViaDifferentUidError) { 805 LOG(INFO) << "ReconcileSecondaryAcessViaDifferentUidError"; 806 reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_CE, 807 /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ false, kSystemUid); 808 } 809 810 class ProfileTest : public DexoptTest { 811 protected: 812 std::string cur_profile_; 813 std::string ref_profile_; 814 std::string snap_profile_; 815 816 static constexpr const char* kPrimaryProfile = "primary.prof"; 817 818 virtual void SetUp() { 819 DexoptTest::SetUp(); 820 cur_profile_ = create_current_profile_path( 821 kTestUserId, package_name_, kPrimaryProfile, /*is_secondary_dex*/ false); 822 ref_profile_ = create_reference_profile_path(package_name_, kPrimaryProfile, 823 /*is_secondary_dex*/ false); 824 snap_profile_ = create_snapshot_profile_path(package_name_, kPrimaryProfile); 825 } 826 827 void SetupProfile(const std::string& path, uid_t uid, gid_t gid, mode_t mode, 828 int32_t num_dex) { 829 run_cmd("profman --generate-test-profile-seed=" + std::to_string(num_dex) + 830 " --generate-test-profile-num-dex=" + std::to_string(num_dex) + 831 " --generate-test-profile=" + path); 832 ::chmod(path.c_str(), mode); 833 ::chown(path.c_str(), uid, gid); 834 } 835 836 void SetupProfiles(bool setup_ref) { 837 SetupProfile(cur_profile_, kTestAppUid, kTestAppGid, 0600, 1); 838 if (setup_ref) { 839 SetupProfile(ref_profile_, kTestAppUid, kTestAppGid, 0600, 2); 840 } 841 } 842 843 void createProfileSnapshot(int32_t appid, const std::string& package_name, 844 bool expected_result) { 845 bool result; 846 ASSERT_BINDER_SUCCESS(service_->createProfileSnapshot( 847 appid, package_name, kPrimaryProfile, apk_path_, &result)); 848 ASSERT_EQ(expected_result, result); 849 850 if (!expected_result) { 851 // Do not check the files if we expect to fail. 852 return; 853 } 854 855 // Check that the snapshot was created witht he expected acess flags. 856 CheckFileAccess(snap_profile_, kSystemUid, kSystemGid, 0600 | S_IFREG); 857 858 // The snapshot should be equivalent to the merge of profiles. 859 std::string expected_profile_content = snap_profile_ + ".expected"; 860 run_cmd("rm -f " + expected_profile_content); 861 run_cmd("touch " + expected_profile_content); 862 run_cmd("profman --profile-file=" + cur_profile_ + 863 " --profile-file=" + ref_profile_ + 864 " --reference-profile-file=" + expected_profile_content + 865 " --apk=" + apk_path_); 866 867 ASSERT_TRUE(AreFilesEqual(expected_profile_content, snap_profile_)); 868 869 pid_t pid = fork(); 870 if (pid == 0) { 871 /* child */ 872 TransitionToSystemServer(); 873 874 // System server should be able to open the the spanshot. 875 unique_fd fd(open(snap_profile_.c_str(), O_RDONLY)); 876 ASSERT_TRUE(fd > -1) << "Failed to open profile as kSystemUid: " << strerror(errno); 877 _exit(0); 878 } 879 /* parent */ 880 ASSERT_TRUE(WIFEXITED(wait_child(pid))); 881 } 882 883 void mergePackageProfiles(const std::string& package_name, 884 const std::string& code_path, 885 bool expected_result) { 886 bool result; 887 ASSERT_BINDER_SUCCESS(service_->mergeProfiles( 888 kTestAppUid, package_name, code_path, &result)); 889 ASSERT_EQ(expected_result, result); 890 891 if (!expected_result) { 892 // Do not check the files if we expect to fail. 893 return; 894 } 895 896 // Check that the snapshot was created witht he expected acess flags. 897 CheckFileAccess(ref_profile_, kTestAppUid, kTestAppUid, 0600 | S_IFREG); 898 899 // The snapshot should be equivalent to the merge of profiles. 900 std::string ref_profile_content = ref_profile_ + ".expected"; 901 run_cmd("rm -f " + ref_profile_content); 902 run_cmd("touch " + ref_profile_content); 903 run_cmd("profman --profile-file=" + cur_profile_ + 904 " --profile-file=" + ref_profile_ + 905 " --reference-profile-file=" + ref_profile_content); 906 907 ASSERT_TRUE(AreFilesEqual(ref_profile_content, ref_profile_)); 908 } 909 910 // TODO(calin): add dex metadata tests once the ART change is merged. 911 void preparePackageProfile(const std::string& package_name, const std::string& profile_name, 912 bool expected_result) { 913 bool result; 914 ASSERT_BINDER_SUCCESS(service_->prepareAppProfile( 915 package_name, kTestUserId, kTestAppId, profile_name, apk_path_, 916 /*dex_metadata*/ nullptr, &result)); 917 ASSERT_EQ(expected_result, result); 918 919 if (!expected_result) { 920 // Do not check the files if we expect to fail. 921 return; 922 } 923 924 std::string code_path_cur_prof = create_current_profile_path( 925 kTestUserId, package_name, profile_name, /*is_secondary_dex*/ false); 926 std::string code_path_ref_profile = create_reference_profile_path(package_name, 927 profile_name, /*is_secondary_dex*/ false); 928 929 // Check that we created the current profile. 930 CheckFileAccess(code_path_cur_prof, kTestAppUid, kTestAppUid, 0600 | S_IFREG); 931 932 // Without dex metadata we don't generate a reference profile. 933 ASSERT_EQ(-1, access(code_path_ref_profile.c_str(), R_OK)); 934 } 935 936 protected: 937 void TransitionToSystemServer() { 938 ASSERT_TRUE(DropCapabilities(kSystemUid, kSystemGid)); 939 int32_t res = selinux_android_setcon("u:r:system_server:s0"); 940 ASSERT_EQ(0, res) << "Failed to setcon " << strerror(errno); 941 } 942 943 bool AreFilesEqual(const std::string& file1, const std::string& file2) { 944 std::vector<uint8_t> content1; 945 std::vector<uint8_t> content2; 946 947 if (!ReadAll(file1, &content1)) return false; 948 if (!ReadAll(file2, &content2)) return false; 949 return content1 == content2; 950 } 951 952 bool ReadAll(const std::string& file, std::vector<uint8_t>* content) { 953 unique_fd fd(open(file.c_str(), O_RDONLY)); 954 if (fd < 0) { 955 PLOG(ERROR) << "Failed to open " << file; 956 return false; 957 } 958 struct stat st; 959 if (fstat(fd, &st) != 0) { 960 PLOG(ERROR) << "Failed to stat " << file; 961 return false; 962 } 963 content->resize(st.st_size); 964 bool result = ReadFully(fd, content->data(), content->size()); 965 if (!result) { 966 PLOG(ERROR) << "Failed to read " << file; 967 } 968 return result; 969 } 970 }; 971 972 TEST_F(ProfileTest, ProfileSnapshotOk) { 973 LOG(INFO) << "ProfileSnapshotOk"; 974 975 SetupProfiles(/*setup_ref*/ true); 976 createProfileSnapshot(kTestAppId, package_name_, /*expected_result*/ true); 977 } 978 979 // The reference profile is created on the fly. We need to be able to 980 // snapshot without one. 981 TEST_F(ProfileTest, ProfileSnapshotOkNoReference) { 982 LOG(INFO) << "ProfileSnapshotOkNoReference"; 983 984 SetupProfiles(/*setup_ref*/ false); 985 createProfileSnapshot(kTestAppId, package_name_, /*expected_result*/ true); 986 } 987 988 TEST_F(ProfileTest, ProfileSnapshotFailWrongPackage) { 989 LOG(INFO) << "ProfileSnapshotFailWrongPackage"; 990 991 SetupProfiles(/*setup_ref*/ true); 992 createProfileSnapshot(kTestAppId, "not.there", /*expected_result*/ false); 993 } 994 995 TEST_F(ProfileTest, ProfileSnapshotDestroySnapshot) { 996 LOG(INFO) << "ProfileSnapshotDestroySnapshot"; 997 998 SetupProfiles(/*setup_ref*/ true); 999 createProfileSnapshot(kTestAppId, package_name_, /*expected_result*/ true); 1000 1001 ASSERT_BINDER_SUCCESS(service_->destroyProfileSnapshot(package_name_, kPrimaryProfile)); 1002 struct stat st; 1003 ASSERT_EQ(-1, stat(snap_profile_.c_str(), &st)); 1004 ASSERT_EQ(ENOENT, errno); 1005 } 1006 1007 TEST_F(ProfileTest, ProfileMergeOk) { 1008 LOG(INFO) << "ProfileMergeOk"; 1009 1010 SetupProfiles(/*setup_ref*/ true); 1011 mergePackageProfiles(package_name_, "primary.prof", /*expected_result*/ true); 1012 } 1013 1014 // The reference profile is created on the fly. We need to be able to 1015 // merge without one. 1016 TEST_F(ProfileTest, ProfileMergeOkNoReference) { 1017 LOG(INFO) << "ProfileMergeOkNoReference"; 1018 1019 SetupProfiles(/*setup_ref*/ false); 1020 mergePackageProfiles(package_name_, "primary.prof", /*expected_result*/ true); 1021 } 1022 1023 TEST_F(ProfileTest, ProfileMergeFailWrongPackage) { 1024 LOG(INFO) << "ProfileMergeFailWrongPackage"; 1025 1026 SetupProfiles(/*setup_ref*/ true); 1027 mergePackageProfiles("not.there", "primary.prof", /*expected_result*/ false); 1028 } 1029 1030 TEST_F(ProfileTest, ProfileDirOk) { 1031 LOG(INFO) << "ProfileDirOk"; 1032 1033 std::string cur_profile_dir = create_primary_current_profile_package_dir_path( 1034 kTestUserId, package_name_); 1035 std::string cur_profile_file = create_current_profile_path(kTestUserId, package_name_, 1036 kPrimaryProfile, /*is_secondary_dex*/false); 1037 std::string ref_profile_dir = create_primary_reference_profile_package_dir_path(package_name_); 1038 1039 CheckFileAccess(cur_profile_dir, kTestAppUid, kTestAppUid, 0700 | S_IFDIR); 1040 CheckFileAccess(ref_profile_dir, kSystemUid, kTestAppGid, 0770 | S_IFDIR); 1041 } 1042 1043 // Verify that the profile directories are fixed up during an upgrade. 1044 // (The reference profile directory is prepared lazily). 1045 TEST_F(ProfileTest, ProfileDirOkAfterFixup) { 1046 LOG(INFO) << "ProfileDirOkAfterFixup"; 1047 1048 std::string cur_profile_dir = create_primary_current_profile_package_dir_path( 1049 kTestUserId, package_name_); 1050 std::string cur_profile_file = create_current_profile_path(kTestUserId, package_name_, 1051 kPrimaryProfile, /*is_secondary_dex*/false); 1052 std::string ref_profile_dir = create_primary_reference_profile_package_dir_path(package_name_); 1053 1054 // Simulate a pre-P setup by changing the owner to kTestAppGid and permissions to 0700. 1055 ASSERT_EQ(0, chown(ref_profile_dir.c_str(), kTestAppGid, kTestAppGid)); 1056 ASSERT_EQ(0, chmod(ref_profile_dir.c_str(), 0700)); 1057 1058 // Run createAppData again which will offer to fix-up the profile directories. 1059 ASSERT_BINDER_SUCCESS(service_->createAppData( 1060 volume_uuid_, 1061 package_name_, 1062 kTestUserId, 1063 kAppDataFlags, 1064 kTestAppUid, 1065 se_info_, 1066 kOSdkVersion, 1067 &ce_data_inode_)); 1068 1069 // Check the file access. 1070 CheckFileAccess(cur_profile_dir, kTestAppUid, kTestAppUid, 0700 | S_IFDIR); 1071 CheckFileAccess(ref_profile_dir, kSystemUid, kTestAppGid, 0770 | S_IFDIR); 1072 } 1073 1074 TEST_F(ProfileTest, ProfilePrepareOk) { 1075 LOG(INFO) << "ProfilePrepareOk"; 1076 preparePackageProfile(package_name_, "split.prof", /*expected_result*/ true); 1077 } 1078 1079 TEST_F(ProfileTest, ProfilePrepareFailInvalidPackage) { 1080 LOG(INFO) << "ProfilePrepareFailInvalidPackage"; 1081 preparePackageProfile("not.there.package", "split.prof", /*expected_result*/ false); 1082 } 1083 1084 TEST_F(ProfileTest, ProfilePrepareFailProfileChangedUid) { 1085 LOG(INFO) << "ProfilePrepareFailProfileChangedUid"; 1086 SetupProfiles(/*setup_ref*/ false); 1087 // Change the uid on the profile to trigger a failure. 1088 ::chown(cur_profile_.c_str(), kTestAppUid + 1, kTestAppGid + 1); 1089 preparePackageProfile(package_name_, "primary.prof", /*expected_result*/ false); 1090 } 1091 1092 1093 class BootProfileTest : public ProfileTest { 1094 public: 1095 virtual void setup() { 1096 ProfileTest::SetUp(); 1097 intial_android_profiles_dir = android_profiles_dir; 1098 } 1099 1100 virtual void TearDown() { 1101 android_profiles_dir = intial_android_profiles_dir; 1102 ProfileTest::TearDown(); 1103 } 1104 1105 void UpdateAndroidProfilesDir(const std::string& profile_dir) { 1106 android_profiles_dir = profile_dir; 1107 // We need to create the reference profile directory in the new profile dir. 1108 run_cmd("mkdir -p " + profile_dir + "/ref"); 1109 } 1110 1111 void createBootImageProfileSnapshot(const std::string& classpath, bool expected_result) { 1112 bool result; 1113 ASSERT_BINDER_SUCCESS(service_->createProfileSnapshot( 1114 -1, "android", "android.prof", classpath, &result)); 1115 ASSERT_EQ(expected_result, result); 1116 1117 if (!expected_result) { 1118 // Do not check the files if we expect to fail. 1119 return; 1120 } 1121 1122 // Check that the snapshot was created with he expected access flags. 1123 const std::string boot_profile = create_snapshot_profile_path("android", "android.prof"); 1124 CheckFileAccess(boot_profile, kSystemUid, kSystemGid, 0600 | S_IFREG); 1125 1126 pid_t pid = fork(); 1127 if (pid == 0) { 1128 /* child */ 1129 TransitionToSystemServer(); 1130 1131 // System server should be able to open the snapshot. 1132 unique_fd fd(open(boot_profile.c_str(), O_RDONLY)); 1133 ASSERT_TRUE(fd > -1) << "Failed to open profile as kSystemUid: " << strerror(errno); 1134 _exit(0); 1135 } 1136 /* parent */ 1137 ASSERT_TRUE(WIFEXITED(wait_child(pid))); 1138 } 1139 protected: 1140 std::string intial_android_profiles_dir; 1141 }; 1142 1143 TEST_F(BootProfileTest, BootProfileSnapshotOk) { 1144 LOG(INFO) << "BootProfileSnapshotOk"; 1145 char* boot_classpath = getenv("BOOTCLASSPATH"); 1146 ASSERT_TRUE(boot_classpath != nullptr); 1147 createBootImageProfileSnapshot(boot_classpath, /*expected_result*/ true); 1148 } 1149 1150 TEST_F(BootProfileTest, BootProfileSnapshotFailEmptyClasspath) { 1151 LOG(INFO) << "BootProfileSnapshotFailEmptyClasspath"; 1152 1153 createBootImageProfileSnapshot(/*boot_classpath*/ "", /*expected_result*/ false); 1154 } 1155 1156 TEST_F(BootProfileTest, BootProfileSnapshotOkNoProfiles) { 1157 LOG(INFO) << "BootProfileSnapshotOkNoProfiles"; 1158 char* boot_classpath = getenv("BOOTCLASSPATH"); 1159 ASSERT_TRUE(boot_classpath != nullptr); 1160 1161 // The app_apk_dir has no profiles. So we shouldn't be able to merge anything. 1162 // Still, this is not a failure case. 1163 UpdateAndroidProfilesDir(app_apk_dir_); 1164 createBootImageProfileSnapshot(boot_classpath, /*expected_result*/ true); 1165 } 1166 1167 // Verify that profile collection. 1168 TEST_F(BootProfileTest, CollectProfiles) { 1169 LOG(INFO) << "CollectProfiles"; 1170 1171 // Create some profile directories mimicking the real profile structure. 1172 run_cmd("mkdir -p " + app_private_dir_de_ + "/profiles/ref"); 1173 run_cmd("mkdir -p " + app_private_dir_de_ + "/profiles/cur/0/"); 1174 run_cmd("mkdir -p " + app_private_dir_de_ + "/profiles/cur/1/"); 1175 // Create an empty profile. 1176 run_cmd("touch " + app_private_dir_de_ + "/profiles/cur/1/primary.prof"); 1177 // Create a random file. 1178 run_cmd("touch " + app_private_dir_de_ + "/profiles/cur/0/non.profile.file"); 1179 1180 // Create some non-empty profiles. 1181 std::string current_prof = app_private_dir_de_ + "/profiles/cur/0/primary.prof"; 1182 run_cmd("echo 1 > " + current_prof); 1183 std::string ref_prof = app_private_dir_de_ + "/profiles/ref/primary.prof"; 1184 run_cmd("echo 1 > " + ref_prof); 1185 1186 UpdateAndroidProfilesDir(app_private_dir_de_ + "/profiles"); 1187 1188 std::vector<std::string> profiles; 1189 collect_profiles(&profiles); 1190 1191 // Only two profiles should be in the output. 1192 ASSERT_EQ(2u, profiles.size()); 1193 ASSERT_TRUE(std::find(profiles.begin(), profiles.end(), current_prof) != profiles.end()); 1194 ASSERT_TRUE(std::find(profiles.begin(), profiles.end(), ref_prof) != profiles.end()); 1195 } 1196 1197 TEST_F(DexoptTest, select_execution_binary) { 1198 LOG(INFO) << "DexoptTestselect_execution_binary"; 1199 1200 std::string release_str = app_private_dir_ce_ + "/release"; 1201 std::string debug_str = app_private_dir_ce_ + "/debug"; 1202 1203 // Setup the binaries. Note that we only need executable files to actually 1204 // test the execution binary selection 1205 run_cmd("touch " + release_str); 1206 run_cmd("touch " + debug_str); 1207 run_cmd("chmod 777 " + release_str); 1208 run_cmd("chmod 777 " + debug_str); 1209 1210 const char* release = release_str.c_str(); 1211 const char* debug = debug_str.c_str(); 1212 1213 ASSERT_STREQ(release, select_execution_binary( 1214 release, 1215 debug, 1216 /*background_job_compile=*/ false, 1217 /*is_debug_runtime=*/ false, 1218 /*is_release=*/ false, 1219 /*is_debuggable_build=*/ false)); 1220 1221 ASSERT_STREQ(release, select_execution_binary( 1222 release, 1223 debug, 1224 /*background_job_compile=*/ true, 1225 /*is_debug_runtime=*/ false, 1226 /*is_release=*/ true, 1227 /*is_debuggable_build=*/ true)); 1228 1229 ASSERT_STREQ(debug, select_execution_binary( 1230 release, 1231 debug, 1232 /*background_job_compile=*/ false, 1233 /*is_debug_runtime=*/ true, 1234 /*is_release=*/ false, 1235 /*is_debuggable_build=*/ false)); 1236 1237 ASSERT_STREQ(debug, select_execution_binary( 1238 release, 1239 debug, 1240 /*background_job_compile=*/ true, 1241 /*is_debug_runtime=*/ false, 1242 /*is_release=*/ false, 1243 /*is_debuggable_build=*/ true)); 1244 1245 1246 // Select the release when the debug file is not there. 1247 ASSERT_STREQ(release, select_execution_binary( 1248 release, 1249 "does_not_exist", 1250 /*background_job_compile=*/ false, 1251 /*is_debug_runtime=*/ true, 1252 /*is_release=*/ false, 1253 /*is_debuggable_build=*/ false)); 1254 } 1255 1256 } // namespace installd 1257 } // namespace android 1258