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