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