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