blob: ea52c0e7b57082ef327fef7d6f24216d22a774c9 [file] [log] [blame]
Calin Juravle7d765462017-09-04 15:57:10 -07001/*
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
Calin Juravle0d0a4922018-01-23 19:54:11 -080017#include <cstdlib>
Calin Juravle29591732017-11-20 17:46:19 -080018#include <fcntl.h>
Calin Juravle7d765462017-09-04 15:57:10 -070019#include <stdlib.h>
20#include <string.h>
Calin Juravle29591732017-11-20 17:46:19 -080021#include <sys/types.h>
22#include <sys/stat.h>
Calin Juravle7d765462017-09-04 15:57:10 -070023
Calin Juravle29591732017-11-20 17:46:19 -080024#include <android-base/file.h>
Calin Juravle7d765462017-09-04 15:57:10 -070025#include <android-base/logging.h>
26#include <android-base/stringprintf.h>
Calin Juravle29591732017-11-20 17:46:19 -080027#include <android-base/unique_fd.h>
28
Calin Juravle7d765462017-09-04 15:57:10 -070029#include <cutils/properties.h>
Calin Juravle29591732017-11-20 17:46:19 -080030
Calin Juravle7d765462017-09-04 15:57:10 -070031#include <gtest/gtest.h>
32
Calin Juravle29591732017-11-20 17:46:19 -080033#include <selinux/android.h>
34#include <selinux/avc.h>
35
Calin Juravle7d765462017-09-04 15:57:10 -070036#include "dexopt.h"
37#include "InstalldNativeService.h"
38#include "globals.h"
39#include "tests/test_utils.h"
40#include "utils.h"
41
Calin Juravle29591732017-11-20 17:46:19 -080042using android::base::ReadFully;
43using android::base::unique_fd;
44
Calin Juravle7d765462017-09-04 15:57:10 -070045namespace android {
46namespace installd {
47
48// TODO(calin): try to dedup this code.
49#if defined(__arm__)
50static const std::string kRuntimeIsa = "arm";
51#elif defined(__aarch64__)
52static const std::string kRuntimeIsa = "arm64";
53#elif defined(__mips__) && !defined(__LP64__)
54static const std::string kRuntimeIsa = "mips";
55#elif defined(__mips__) && defined(__LP64__)
56static const std::string kRuntimeIsa = "mips64";
57#elif defined(__i386__)
58static const std::string kRuntimeIsa = "x86";
59#elif defined(__x86_64__)
60static const std::string kRuntimeIsa = "x86_64";
61#else
62static const std::string kRuntimeIsa = "none";
63#endif
64
65int get_property(const char *key, char *value, const char *default_value) {
66 return property_get(key, value, default_value);
67}
68
69bool calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
70 const char *instruction_set) {
71 return calculate_oat_file_path_default(path, oat_dir, apk_path, instruction_set);
72}
73
74bool calculate_odex_file_path(char path[PKG_PATH_MAX], const char *apk_path,
75 const char *instruction_set) {
76 return calculate_odex_file_path_default(path, apk_path, instruction_set);
77}
78
79bool create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *instruction_set) {
80 return create_cache_path_default(path, src, instruction_set);
81}
82
83static void run_cmd(const std::string& cmd) {
84 system(cmd.c_str());
85}
86
87static void mkdir(const std::string& path, uid_t owner, gid_t group, mode_t mode) {
88 ::mkdir(path.c_str(), mode);
89 ::chown(path.c_str(), owner, group);
90 ::chmod(path.c_str(), mode);
91}
92
Calin Juravle29591732017-11-20 17:46:19 -080093static int log_callback(int type, const char *fmt, ...) { // NOLINT
94 va_list ap;
95 int priority;
96
97 switch (type) {
98 case SELINUX_WARNING:
99 priority = ANDROID_LOG_WARN;
100 break;
101 case SELINUX_INFO:
102 priority = ANDROID_LOG_INFO;
103 break;
104 default:
105 priority = ANDROID_LOG_ERROR;
106 break;
107 }
108 va_start(ap, fmt);
109 LOG_PRI_VA(priority, "SELinux", fmt, ap);
110 va_end(ap);
111 return 0;
112}
113
114static bool init_selinux() {
115 int selinux_enabled = (is_selinux_enabled() > 0);
116
117 union selinux_callback cb;
118 cb.func_log = log_callback;
119 selinux_set_callback(SELINUX_CB_LOG, cb);
120
121 if (selinux_enabled && selinux_status_open(true) < 0) {
122 LOG(ERROR) << "Could not open selinux status; exiting";
123 return false;
124 }
125
126 return true;
127}
128
Calin Juravle7d765462017-09-04 15:57:10 -0700129// Base64 encoding of a simple dex files with 2 methods.
130static const char kDexFile[] =
131 "UEsDBBQAAAAIAOiOYUs9y6BLCgEAABQCAAALABwAY2xhc3Nlcy5kZXhVVAkAA/Ns+lkOHv1ZdXgL"
132 "AAEEI+UCAASIEwAAS0mt4DIwNmX4qpn7j/2wA7v7N+ZvoQpCJRlVx5SWa4YaiDAxMBQwMDBUhJkI"
133 "MUBBDyMDAzsDRJwFxAdioBDDHAYEYAbiFUAM1M5wAIhFGCGKDIDYAogdgNgDiH2BOAiI0xghekDm"
134 "sQIxGxQzM6ACRijNhCbOhCZfyohdPYyuh8szgtVkMkLsLhAAqeCDi+ejibPZZOZlltgxsDnqZSWW"
135 "JTKwOUFoZh9HayDhZM0g5AMS0M9JzEvX90/KSk0usWZgDAMaws5nAyXBzmpoYGlgAjsAyJoBMp0b"
136 "zQ8gGhbOTEhhzYwU3qxIYc2GFN6MClC/AhUyKUDMAYU9M1Qc5F8GKBscVgIQM0FxCwBQSwECHgMU"
137 "AAAACADojmFLPcugSwoBAAAUAgAACwAYAAAAAAAAAAAAoIEAAAAAY2xhc3Nlcy5kZXhVVAUAA/Ns"
138 "+ll1eAsAAQQj5QIABIgTAABQSwUGAAAAAAEAAQBRAAAATwEAAAAA";
139
140
141class DexoptTest : public testing::Test {
142protected:
143 static constexpr bool kDebug = false;
144 static constexpr uid_t kSystemUid = 1000;
145 static constexpr uid_t kSystemGid = 1000;
146 static constexpr int32_t kOSdkVersion = 25;
147 static constexpr int32_t kAppDataFlags = FLAG_STORAGE_CE | FLAG_STORAGE_DE;
Calin Juravle7d765462017-09-04 15:57:10 -0700148 static constexpr int32_t kTestUserId = 0;
Calin Juravled2affb82017-11-28 17:41:43 -0800149 static constexpr uid_t kTestAppId = 19999;
150
151 const gid_t kTestAppUid = multiuser_get_uid(kTestUserId, kTestAppId);
152 const uid_t kTestAppGid = multiuser_get_shared_gid(kTestUserId, kTestAppId);
Calin Juravle7d765462017-09-04 15:57:10 -0700153
154 InstalldNativeService* service_;
155 std::unique_ptr<std::string> volume_uuid_;
156 std::string package_name_;
Calin Juravle0d0a4922018-01-23 19:54:11 -0800157 std::string apk_path_;
Calin Juravle7d765462017-09-04 15:57:10 -0700158 std::string app_apk_dir_;
159 std::string app_private_dir_ce_;
160 std::string app_private_dir_de_;
161 std::string se_info_;
Calin Juravlec4f6a0b2018-02-01 01:27:24 +0000162 std::string app_oat_dir_;
Calin Juravle7d765462017-09-04 15:57:10 -0700163
164 int64_t ce_data_inode_;
165
166 std::string secondary_dex_ce_;
167 std::string secondary_dex_ce_link_;
168 std::string secondary_dex_de_;
169
170 virtual void SetUp() {
171 setenv("ANDROID_LOG_TAGS", "*:v", 1);
172 android::base::InitLogging(nullptr);
Calin Juravle29591732017-11-20 17:46:19 -0800173 // Initialize the globals holding the file system main paths (/data/, /system/ etc..).
174 // This is needed in order to compute the application and profile paths.
175 ASSERT_TRUE(init_globals_from_data_and_root());
176 // Initialize selinux log callbacks.
177 // This ensures that selinux is up and running and re-directs the selinux messages
178 // to logcat (in order to make it easier to investigate test results).
179 ASSERT_TRUE(init_selinux());
Calin Juravle7d765462017-09-04 15:57:10 -0700180 service_ = new InstalldNativeService();
181
182 volume_uuid_ = nullptr;
183 package_name_ = "com.installd.test.dexopt";
184 se_info_ = "default";
Calin Juravle7d765462017-09-04 15:57:10 -0700185 app_apk_dir_ = android_app_dir + package_name_;
186
187 create_mock_app();
188 }
189
190 virtual void TearDown() {
191 if (!kDebug) {
192 service_->destroyAppData(
193 volume_uuid_, package_name_, kTestUserId, kAppDataFlags, ce_data_inode_);
194 run_cmd("rm -rf " + app_apk_dir_);
195 run_cmd("rm -rf " + app_private_dir_ce_);
196 run_cmd("rm -rf " + app_private_dir_de_);
197 }
198 delete service_;
199 }
200
201 void create_mock_app() {
202 // Create the oat dir.
Calin Juravlec4f6a0b2018-02-01 01:27:24 +0000203 app_oat_dir_ = app_apk_dir_ + "/oat";
Calin Juravle7d765462017-09-04 15:57:10 -0700204 mkdir(app_apk_dir_, kSystemUid, kSystemGid, 0755);
Calin Juravlec4f6a0b2018-02-01 01:27:24 +0000205 service_->createOatDir(app_oat_dir_, kRuntimeIsa);
Calin Juravle7d765462017-09-04 15:57:10 -0700206
207 // Copy the primary apk.
Calin Juravle0d0a4922018-01-23 19:54:11 -0800208 apk_path_ = app_apk_dir_ + "/base.jar";
209 ASSERT_TRUE(WriteBase64ToFile(kDexFile, apk_path_, kSystemUid, kSystemGid, 0644));
Calin Juravle7d765462017-09-04 15:57:10 -0700210
211 // Create the app user data.
212 ASSERT_TRUE(service_->createAppData(
213 volume_uuid_,
214 package_name_,
215 kTestUserId,
216 kAppDataFlags,
217 kTestAppUid,
218 se_info_,
219 kOSdkVersion,
220 &ce_data_inode_).isOk());
221
222 // Create a secondary dex file on CE storage
223 const char* volume_uuid_cstr = volume_uuid_ == nullptr ? nullptr : volume_uuid_->c_str();
224 app_private_dir_ce_ = create_data_user_ce_package_path(
225 volume_uuid_cstr, kTestUserId, package_name_.c_str());
226 secondary_dex_ce_ = app_private_dir_ce_ + "/secondary_ce.jar";
227 ASSERT_TRUE(WriteBase64ToFile(kDexFile, secondary_dex_ce_, kTestAppUid, kTestAppGid, 0600));
228 std::string app_private_dir_ce_link = create_data_user_ce_package_path_as_user_link(
229 volume_uuid_cstr, kTestUserId, package_name_.c_str());
230 secondary_dex_ce_link_ = app_private_dir_ce_link + "/secondary_ce.jar";
231
232 // Create a secondary dex file on DE storage.
233 app_private_dir_de_ = create_data_user_de_package_path(
234 volume_uuid_cstr, kTestUserId, package_name_.c_str());
235 secondary_dex_de_ = app_private_dir_de_ + "/secondary_de.jar";
236 ASSERT_TRUE(WriteBase64ToFile(kDexFile, secondary_dex_de_, kTestAppUid, kTestAppGid, 0600));
237
238 // Fix app data uid.
239 ASSERT_TRUE(service_->fixupAppData(volume_uuid_, kTestUserId).isOk());
240 }
241
242
Calin Juravle29591732017-11-20 17:46:19 -0800243 std::string GetSecondaryDexArtifact(const std::string& path, const std::string& type) {
Calin Juravle7d765462017-09-04 15:57:10 -0700244 std::string::size_type end = path.rfind('.');
245 std::string::size_type start = path.rfind('/', end);
246 return path.substr(0, start) + "/oat/" + kRuntimeIsa + "/" +
247 path.substr(start + 1, end - start) + type;
248 }
249
Calin Juravle29591732017-11-20 17:46:19 -0800250 void CompileSecondaryDex(const std::string& path, int32_t dex_storage_flag,
Calin Juravle7d765462017-09-04 15:57:10 -0700251 bool should_binder_call_succeed, bool should_dex_be_compiled = true,
Calin Juravled2affb82017-11-28 17:41:43 -0800252 int32_t uid = -1) {
253 if (uid == -1) {
254 uid = kTestAppUid;
255 }
Calin Juravle7d765462017-09-04 15:57:10 -0700256 std::unique_ptr<std::string> package_name_ptr(new std::string(package_name_));
257 int32_t dexopt_needed = 0; // does not matter;
258 std::unique_ptr<std::string> out_path = nullptr; // does not matter
259 int32_t dex_flags = DEXOPT_SECONDARY_DEX | dex_storage_flag;
260 std::string compiler_filter = "speed-profile";
261 std::unique_ptr<std::string> class_loader_context_ptr(new std::string("&"));
262 std::unique_ptr<std::string> se_info_ptr(new std::string(se_info_));
263 bool downgrade = false;
David Brazdil570d3982018-01-16 20:15:43 +0000264 int32_t target_sdk_version = 0; // default
Calin Juravlec4f6a0b2018-02-01 01:27:24 +0000265 std::unique_ptr<std::string> profile_name_ptr = nullptr;
Calin Juravle62c5a372018-02-01 17:03:23 +0000266 std::unique_ptr<std::string> dm_path_ptr = nullptr;
Calin Juravle7d765462017-09-04 15:57:10 -0700267
268 binder::Status result = service_->dexopt(path,
269 uid,
270 package_name_ptr,
271 kRuntimeIsa,
272 dexopt_needed,
273 out_path,
274 dex_flags,
275 compiler_filter,
276 volume_uuid_,
277 class_loader_context_ptr,
278 se_info_ptr,
David Brazdil570d3982018-01-16 20:15:43 +0000279 downgrade,
Calin Juravle408cd4a2018-01-20 23:34:18 -0800280 target_sdk_version,
Calin Juravle62c5a372018-02-01 17:03:23 +0000281 profile_name_ptr,
282 dm_path_ptr);
Calin Juravle7d765462017-09-04 15:57:10 -0700283 ASSERT_EQ(should_binder_call_succeed, result.isOk());
284 int expected_access = should_dex_be_compiled ? 0 : -1;
Calin Juravle29591732017-11-20 17:46:19 -0800285 std::string odex = GetSecondaryDexArtifact(path, "odex");
286 std::string vdex = GetSecondaryDexArtifact(path, "vdex");
287 std::string art = GetSecondaryDexArtifact(path, "art");
Calin Juravle7d765462017-09-04 15:57:10 -0700288 ASSERT_EQ(expected_access, access(odex.c_str(), R_OK));
289 ASSERT_EQ(expected_access, access(vdex.c_str(), R_OK));
290 ASSERT_EQ(-1, access(art.c_str(), R_OK)); // empty profiles do not generate an image.
291 }
292
293 void reconcile_secondary_dex(const std::string& path, int32_t storage_flag,
294 bool should_binder_call_succeed, bool should_dex_exist, bool should_dex_be_deleted,
Calin Juravled2affb82017-11-28 17:41:43 -0800295 int32_t uid = -1, std::string* package_override = nullptr) {
296 if (uid == -1) {
297 uid = kTestAppUid;
298 }
Calin Juravle7d765462017-09-04 15:57:10 -0700299 std::vector<std::string> isas;
300 isas.push_back(kRuntimeIsa);
301 bool out_secondary_dex_exists = false;
302 binder::Status result = service_->reconcileSecondaryDexFile(
303 path,
304 package_override == nullptr ? package_name_ : *package_override,
305 uid,
306 isas,
307 volume_uuid_,
308 storage_flag,
309 &out_secondary_dex_exists);
310
311 ASSERT_EQ(should_binder_call_succeed, result.isOk());
312 ASSERT_EQ(should_dex_exist, out_secondary_dex_exists);
313
314 int expected_access = should_dex_be_deleted ? -1 : 0;
Calin Juravle29591732017-11-20 17:46:19 -0800315 std::string odex = GetSecondaryDexArtifact(path, "odex");
316 std::string vdex = GetSecondaryDexArtifact(path, "vdex");
317 std::string art = GetSecondaryDexArtifact(path, "art");
Calin Juravle7d765462017-09-04 15:57:10 -0700318 ASSERT_EQ(expected_access, access(odex.c_str(), F_OK));
319 ASSERT_EQ(expected_access, access(vdex.c_str(), F_OK));
320 ASSERT_EQ(-1, access(art.c_str(), R_OK)); // empty profiles do not generate an image.
321 }
Calin Juravle29591732017-11-20 17:46:19 -0800322
323 void CheckFileAccess(const std::string& file, uid_t uid, gid_t gid, mode_t mode) {
324 struct stat st;
325 ASSERT_EQ(0, stat(file.c_str(), &st));
326 ASSERT_EQ(uid, st.st_uid);
327 ASSERT_EQ(gid, st.st_gid);
328 ASSERT_EQ(mode, st.st_mode);
329 }
Calin Juravlec4f6a0b2018-02-01 01:27:24 +0000330
331 void CompilePrimaryDexOk(std::string compiler_filter,
332 int32_t dex_flags,
333 const char* oat_dir,
334 int32_t uid,
335 int32_t dexopt_needed,
Calin Juravle62c5a372018-02-01 17:03:23 +0000336 const char* dm_path = nullptr,
Calin Juravlec4f6a0b2018-02-01 01:27:24 +0000337 bool downgrade = false) {
338 return CompilePrimaryDex(
Calin Juravle62c5a372018-02-01 17:03:23 +0000339 compiler_filter, dex_flags, oat_dir, uid, dexopt_needed, dm_path, downgrade, true);
Calin Juravlec4f6a0b2018-02-01 01:27:24 +0000340 }
341
342 void CompilePrimaryDexFail(std::string compiler_filter,
343 int32_t dex_flags,
344 const char* oat_dir,
345 int32_t uid,
346 int32_t dexopt_needed,
Calin Juravle62c5a372018-02-01 17:03:23 +0000347 const char* dm_path = nullptr,
Calin Juravlec4f6a0b2018-02-01 01:27:24 +0000348 bool downgrade = false) {
349 return CompilePrimaryDex(
Calin Juravle62c5a372018-02-01 17:03:23 +0000350 compiler_filter, dex_flags, oat_dir, uid, dexopt_needed, dm_path, downgrade, false);
Calin Juravlec4f6a0b2018-02-01 01:27:24 +0000351 }
352
353 void CompilePrimaryDex(std::string compiler_filter,
354 int32_t dex_flags,
355 const char* oat_dir,
356 int32_t uid,
357 int32_t dexopt_needed,
Calin Juravle62c5a372018-02-01 17:03:23 +0000358 const char* dm_path,
Calin Juravlec4f6a0b2018-02-01 01:27:24 +0000359 bool downgrade,
360 bool should_binder_call_succeed) {
361 std::unique_ptr<std::string> package_name_ptr(new std::string(package_name_));
362 std::unique_ptr<std::string> out_path(
363 oat_dir == nullptr ? nullptr : new std::string(oat_dir));
364 std::unique_ptr<std::string> class_loader_context_ptr(new std::string("&"));
365 std::unique_ptr<std::string> se_info_ptr(new std::string(se_info_));
366 int32_t target_sdk_version = 0; // default
367 std::unique_ptr<std::string> profile_name_ptr(new std::string("primary.prof"));
Calin Juravle62c5a372018-02-01 17:03:23 +0000368 std::unique_ptr<std::string> dm_path_ptr = nullptr;
369 if (dm_path != nullptr) {
370 dm_path_ptr.reset(new std::string(dm_path));
371 }
Calin Juravlec4f6a0b2018-02-01 01:27:24 +0000372
373 bool prof_result;
374 binder::Status prof_binder_result = service_->prepareAppProfile(
375 package_name_, kTestUserId, kTestAppId, *profile_name_ptr, /*code path*/ "base.apk",
376 /*dex_metadata*/ nullptr, &prof_result);
377
378 ASSERT_TRUE(prof_binder_result.isOk());
379 ASSERT_TRUE(prof_result);
380
381 binder::Status result = service_->dexopt(apk_path_,
382 uid,
383 package_name_ptr,
384 kRuntimeIsa,
385 dexopt_needed,
386 out_path,
387 dex_flags,
388 compiler_filter,
389 volume_uuid_,
390 class_loader_context_ptr,
391 se_info_ptr,
392 downgrade,
393 target_sdk_version,
Calin Juravle62c5a372018-02-01 17:03:23 +0000394 profile_name_ptr,
395 dm_path_ptr);
Calin Juravlec4f6a0b2018-02-01 01:27:24 +0000396 ASSERT_EQ(should_binder_call_succeed, result.isOk());
397
398 if (!should_binder_call_succeed) {
399 return;
400 }
401 // Check the access to the compiler output.
402 // - speed-profile artifacts are not world-wide readable.
403 // - files are owned by the system uid.
404 std::string odex = GetPrimaryDexArtifact(oat_dir, apk_path_, "odex");
405 std::string vdex = GetPrimaryDexArtifact(oat_dir, apk_path_, "vdex");
406 std::string art = GetPrimaryDexArtifact(oat_dir, apk_path_, "art");
407
408 mode_t mode = S_IFREG | (compiler_filter == "speed-profile" ? 0640 : 0644);
409 CheckFileAccess(odex, kSystemUid, uid, mode);
410 CheckFileAccess(vdex, kSystemUid, uid, mode);
411 CheckFileAccess(odex, kSystemUid, uid, mode);
412
413 // empty profiles do not generate an image.
414 // todo: add tests with non-empty profiles.
415 struct stat st;
416 ASSERT_EQ(-1, stat(art.c_str(), &st));
417 }
418
419 std::string GetPrimaryDexArtifact(const char* oat_dir,
420 const std::string& dex_path,
421 const std::string& type) {
422 if (oat_dir == nullptr) {
423 std::string path = dex_path;
424 for (auto it = path.begin() + 1; it < path.end(); ++it) {
425 if (*it == '/') {
426 *it = '@';
427 }
428 }
429 return android_data_dir + DALVIK_CACHE + '/' + kRuntimeIsa + "/" + path
430 + "@classes.dex";
431 } else {
432 std::string::size_type name_end = dex_path.rfind('.');
433 std::string::size_type name_start = dex_path.rfind('/');
434 return std::string(oat_dir) + "/" + kRuntimeIsa + "/" +
435 dex_path.substr(name_start + 1, name_end - name_start) + type;
436 }
437 }
Calin Juravle7d765462017-09-04 15:57:10 -0700438};
439
440
441TEST_F(DexoptTest, DexoptSecondaryCe) {
442 LOG(INFO) << "DexoptSecondaryCe";
Calin Juravle29591732017-11-20 17:46:19 -0800443 CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE,
Calin Juravle7d765462017-09-04 15:57:10 -0700444 /*binder_ok*/ true, /*compile_ok*/ true);
445}
446
447TEST_F(DexoptTest, DexoptSecondaryCeLink) {
448 LOG(INFO) << "DexoptSecondaryCeLink";
Calin Juravle29591732017-11-20 17:46:19 -0800449 CompileSecondaryDex(secondary_dex_ce_link_, DEXOPT_STORAGE_CE,
Calin Juravle7d765462017-09-04 15:57:10 -0700450 /*binder_ok*/ true, /*compile_ok*/ true);
451}
452
453TEST_F(DexoptTest, DexoptSecondaryDe) {
454 LOG(INFO) << "DexoptSecondaryDe";
Calin Juravle29591732017-11-20 17:46:19 -0800455 CompileSecondaryDex(secondary_dex_de_, DEXOPT_STORAGE_DE,
Calin Juravle7d765462017-09-04 15:57:10 -0700456 /*binder_ok*/ true, /*compile_ok*/ true);
457}
458
459TEST_F(DexoptTest, DexoptSecondaryDoesNotExist) {
460 LOG(INFO) << "DexoptSecondaryDoesNotExist";
461 // If the file validates but does not exist we do not treat it as an error.
Calin Juravle29591732017-11-20 17:46:19 -0800462 CompileSecondaryDex(secondary_dex_ce_ + "not.there", DEXOPT_STORAGE_CE,
Calin Juravle7d765462017-09-04 15:57:10 -0700463 /*binder_ok*/ true, /*compile_ok*/ false);
464}
465
466TEST_F(DexoptTest, DexoptSecondaryStorageValidationError) {
467 LOG(INFO) << "DexoptSecondaryStorageValidationError";
Calin Juravle29591732017-11-20 17:46:19 -0800468 CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_DE,
Calin Juravle7d765462017-09-04 15:57:10 -0700469 /*binder_ok*/ false, /*compile_ok*/ false);
470}
471
472TEST_F(DexoptTest, DexoptSecondaryAppOwnershipValidationError) {
473 LOG(INFO) << "DexoptSecondaryAppOwnershipValidationError";
Calin Juravle29591732017-11-20 17:46:19 -0800474 CompileSecondaryDex("/data/data/random.app/secondary.jar", DEXOPT_STORAGE_CE,
Calin Juravle7d765462017-09-04 15:57:10 -0700475 /*binder_ok*/ false, /*compile_ok*/ false);
476}
477
478TEST_F(DexoptTest, DexoptSecondaryAcessViaDifferentUidError) {
479 LOG(INFO) << "DexoptSecondaryAcessViaDifferentUidError";
Calin Juravle29591732017-11-20 17:46:19 -0800480 CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE,
Calin Juravle7d765462017-09-04 15:57:10 -0700481 /*binder_ok*/ false, /*compile_ok*/ false, kSystemUid);
482}
483
Calin Juravlec4f6a0b2018-02-01 01:27:24 +0000484TEST_F(DexoptTest, DexoptPrimaryPublic) {
485 LOG(INFO) << "DexoptPrimaryPublic";
486 CompilePrimaryDexOk("verify",
487 DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC,
488 app_oat_dir_.c_str(),
489 kTestAppGid,
490 DEX2OAT_FROM_SCRATCH);
491}
492
493TEST_F(DexoptTest, DexoptPrimaryProfileNonPublic) {
494 LOG(INFO) << "DexoptPrimaryProfileNonPublic";
495 CompilePrimaryDexOk("speed-profile",
496 DEXOPT_BOOTCOMPLETE,
497 app_oat_dir_.c_str(),
498 kTestAppGid,
499 DEX2OAT_FROM_SCRATCH);
500}
501
502TEST_F(DexoptTest, DexoptPrimaryProfilePublic) {
503 LOG(INFO) << "DexoptPrimaryProfilePublic";
504 CompilePrimaryDexOk("verify",
505 DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC,
506 app_oat_dir_.c_str(),
507 kTestAppGid,
508 DEX2OAT_FROM_SCRATCH);
509}
510
511TEST_F(DexoptTest, DexoptPrimaryBackgroundOk) {
512 LOG(INFO) << "DexoptPrimaryBackgroundOk";
513 CompilePrimaryDexOk("speed-profile",
514 DEXOPT_IDLE_BACKGROUND_JOB,
515 app_oat_dir_.c_str(),
516 kTestAppGid,
517 DEX2OAT_FROM_SCRATCH);
518}
519
520TEST_F(DexoptTest, DexoptPrimaryFailedInvalidFilter) {
521 LOG(INFO) << "DexoptPrimaryFailedInvalidFilter";
522 CompilePrimaryDexFail("awesome-filter",
523 DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PUBLIC,
524 app_oat_dir_.c_str(),
525 kTestAppGid,
526 DEX2OAT_FROM_SCRATCH);
527}
528
529class PrimaryDexReCompilationTest : public DexoptTest {
530 public:
531 virtual void SetUp() {
532 DexoptTest::SetUp();
533 CompilePrimaryDexOk("verify",
534 DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC,
535 app_oat_dir_.c_str(),
536 kTestAppGid,
537 DEX2OAT_FROM_SCRATCH);
538 std::string odex = GetSecondaryDexArtifact(apk_path_, "odex");
539 std::string vdex = GetSecondaryDexArtifact(apk_path_, "vdex");
540
541 first_compilation_odex_fd_.reset(open(odex.c_str(), O_RDONLY));
542 first_compilation_vdex_fd_.reset(open(vdex.c_str(), O_RDONLY));
543 }
544
545 virtual void TearDown() {
546 first_compilation_odex_fd_.reset(-1);
547 first_compilation_vdex_fd_.reset(-1);
548 DexoptTest::TearDown();
549 }
550
551 protected:
552 unique_fd first_compilation_odex_fd_;
553 unique_fd first_compilation_vdex_fd_;
554};
555
556TEST_F(PrimaryDexReCompilationTest, DexoptPrimaryUpdateInPlaceVdex) {
557 LOG(INFO) << "DexoptPrimaryUpdateInPlaceVdex";
558
559 CompilePrimaryDexOk("verify",
560 DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PUBLIC,
561 app_oat_dir_.c_str(),
562 kTestAppGid,
563 DEX2OAT_FOR_BOOT_IMAGE);
564}
Calin Juravle7d765462017-09-04 15:57:10 -0700565
566class ReconcileTest : public DexoptTest {
567 virtual void SetUp() {
568 DexoptTest::SetUp();
Calin Juravle29591732017-11-20 17:46:19 -0800569 CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE,
Calin Juravle7d765462017-09-04 15:57:10 -0700570 /*binder_ok*/ true, /*compile_ok*/ true);
Calin Juravle29591732017-11-20 17:46:19 -0800571 CompileSecondaryDex(secondary_dex_de_, DEXOPT_STORAGE_DE,
Calin Juravle7d765462017-09-04 15:57:10 -0700572 /*binder_ok*/ true, /*compile_ok*/ true);
573 }
574};
575
576TEST_F(ReconcileTest, ReconcileSecondaryCeExists) {
577 LOG(INFO) << "ReconcileSecondaryCeExists";
578 reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_CE,
579 /*binder_ok*/ true, /*dex_ok */ true, /*odex_deleted*/ false);
580}
581
582TEST_F(ReconcileTest, ReconcileSecondaryCeLinkExists) {
583 LOG(INFO) << "ReconcileSecondaryCeLinkExists";
584 reconcile_secondary_dex(secondary_dex_ce_link_, FLAG_STORAGE_CE,
585 /*binder_ok*/ true, /*dex_ok */ true, /*odex_deleted*/ false);
586}
587
588TEST_F(ReconcileTest, ReconcileSecondaryDeExists) {
589 LOG(INFO) << "ReconcileSecondaryDeExists";
590 reconcile_secondary_dex(secondary_dex_de_, FLAG_STORAGE_DE,
591 /*binder_ok*/ true, /*dex_ok */ true, /*odex_deleted*/ false);
592}
593
594TEST_F(ReconcileTest, ReconcileSecondaryDeDoesNotExist) {
595 LOG(INFO) << "ReconcileSecondaryDeDoesNotExist";
596 run_cmd("rm -rf " + secondary_dex_de_);
597 reconcile_secondary_dex(secondary_dex_de_, FLAG_STORAGE_DE,
598 /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ true);
599}
600
601TEST_F(ReconcileTest, ReconcileSecondaryStorageValidationError) {
602 // Validation errors will not clean the odex/vdex/art files but will mark
603 // the file as non existent so that the PM knows it should purge it from its
604 // records.
605 LOG(INFO) << "ReconcileSecondaryStorageValidationError";
606 reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_DE,
607 /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ false);
608}
609
610TEST_F(ReconcileTest, ReconcileSecondaryAppOwnershipValidationError) {
611 LOG(INFO) << "ReconcileSecondaryAppOwnershipValidationError";
612 // Attempt to reconcile the dex files of the test app from a different app.
613 std::string another_app = "another.app";
614 reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_CE,
615 /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ false, kSystemUid, &another_app);
616}
617
618TEST_F(ReconcileTest, ReconcileSecondaryAcessViaDifferentUidError) {
619 LOG(INFO) << "ReconcileSecondaryAcessViaDifferentUidError";
620 reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_CE,
621 /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ false, kSystemUid);
622}
623
Calin Juravle29591732017-11-20 17:46:19 -0800624class ProfileTest : public DexoptTest {
625 protected:
626 std::string cur_profile_;
627 std::string ref_profile_;
628 std::string snap_profile_;
629
Calin Juravle824a64d2018-01-18 20:23:17 -0800630 static constexpr const char* kPrimaryProfile = "primary.prof";
631
Calin Juravle29591732017-11-20 17:46:19 -0800632 virtual void SetUp() {
633 DexoptTest::SetUp();
634 cur_profile_ = create_current_profile_path(
Calin Juravle824a64d2018-01-18 20:23:17 -0800635 kTestUserId, package_name_, kPrimaryProfile, /*is_secondary_dex*/ false);
636 ref_profile_ = create_reference_profile_path(package_name_, kPrimaryProfile,
637 /*is_secondary_dex*/ false);
638 snap_profile_ = create_snapshot_profile_path(package_name_, kPrimaryProfile);
Calin Juravle29591732017-11-20 17:46:19 -0800639 }
640
Calin Juravle824a64d2018-01-18 20:23:17 -0800641 void SetupProfile(const std::string& path, uid_t uid, gid_t gid, mode_t mode,
642 int32_t num_dex) {
643 run_cmd("profman --generate-test-profile-seed=" + std::to_string(num_dex) +
644 " --generate-test-profile-num-dex=" + std::to_string(num_dex) +
645 " --generate-test-profile=" + path);
Calin Juravle29591732017-11-20 17:46:19 -0800646 ::chmod(path.c_str(), mode);
647 ::chown(path.c_str(), uid, gid);
648 }
649
650 void SetupProfiles(bool setup_ref) {
651 SetupProfile(cur_profile_, kTestAppUid, kTestAppGid, 0600, 1);
652 if (setup_ref) {
Calin Juravle824a64d2018-01-18 20:23:17 -0800653 SetupProfile(ref_profile_, kTestAppUid, kTestAppGid, 0600, 2);
Calin Juravle29591732017-11-20 17:46:19 -0800654 }
655 }
656
Calin Juravlec3596c32017-12-05 12:29:15 -0800657 void createProfileSnapshot(int32_t appid, const std::string& package_name,
658 bool expected_result) {
Calin Juravle29591732017-11-20 17:46:19 -0800659 bool result;
Calin Juravlec3596c32017-12-05 12:29:15 -0800660 binder::Status binder_result = service_->createProfileSnapshot(
Calin Juravle0d0a4922018-01-23 19:54:11 -0800661 appid, package_name, kPrimaryProfile, apk_path_, &result);
Calin Juravle29591732017-11-20 17:46:19 -0800662 ASSERT_TRUE(binder_result.isOk());
663 ASSERT_EQ(expected_result, result);
664
665 if (!expected_result) {
666 // Do not check the files if we expect to fail.
667 return;
668 }
669
670 // Check that the snapshot was created witht he expected acess flags.
671 CheckFileAccess(snap_profile_, kSystemUid, kSystemGid, 0600 | S_IFREG);
672
673 // The snapshot should be equivalent to the merge of profiles.
674 std::string expected_profile_content = snap_profile_ + ".expected";
675 run_cmd("rm -f " + expected_profile_content);
676 run_cmd("touch " + expected_profile_content);
677 run_cmd("profman --profile-file=" + cur_profile_ +
678 " --profile-file=" + ref_profile_ +
679 " --reference-profile-file=" + expected_profile_content);
680
681 ASSERT_TRUE(AreFilesEqual(expected_profile_content, snap_profile_));
682
683 pid_t pid = fork();
684 if (pid == 0) {
685 /* child */
686 TransitionToSystemServer();
687
688 // System server should be able to open the the spanshot.
689 unique_fd fd(open(snap_profile_.c_str(), O_RDONLY));
690 ASSERT_TRUE(fd > -1) << "Failed to open profile as kSystemUid: " << strerror(errno);
691 _exit(0);
692 }
693 /* parent */
694 ASSERT_TRUE(WIFEXITED(wait_child(pid)));
695 }
696
Calin Juravle408cd4a2018-01-20 23:34:18 -0800697 void mergePackageProfiles(const std::string& package_name,
698 const std::string& code_path,
699 bool expected_result) {
Calin Juravle824a64d2018-01-18 20:23:17 -0800700 bool result;
701 binder::Status binder_result = service_->mergeProfiles(
Calin Juravle408cd4a2018-01-20 23:34:18 -0800702 kTestAppUid, package_name, code_path, &result);
Calin Juravle824a64d2018-01-18 20:23:17 -0800703 ASSERT_TRUE(binder_result.isOk());
704 ASSERT_EQ(expected_result, result);
705
706 if (!expected_result) {
707 // Do not check the files if we expect to fail.
708 return;
709 }
710
711 // Check that the snapshot was created witht he expected acess flags.
712 CheckFileAccess(ref_profile_, kTestAppUid, kTestAppUid, 0600 | S_IFREG);
713
714 // The snapshot should be equivalent to the merge of profiles.
715 std::string ref_profile_content = ref_profile_ + ".expected";
716 run_cmd("rm -f " + ref_profile_content);
717 run_cmd("touch " + ref_profile_content);
718 run_cmd("profman --profile-file=" + cur_profile_ +
719 " --profile-file=" + ref_profile_ +
720 " --reference-profile-file=" + ref_profile_content);
721
722 ASSERT_TRUE(AreFilesEqual(ref_profile_content, ref_profile_));
723 }
724
Calin Juravlec3b049e2018-01-18 22:32:58 -0800725 // TODO(calin): add dex metadata tests once the ART change is merged.
726 void preparePackageProfile(const std::string& package_name, const std::string& profile_name,
727 bool expected_result) {
728 bool result;
729 binder::Status binder_result = service_->prepareAppProfile(
730 package_name, kTestUserId, kTestAppId, profile_name, /*code path*/ "base.apk",
731 /*dex_metadata*/ nullptr, &result);
732 ASSERT_TRUE(binder_result.isOk());
733 ASSERT_EQ(expected_result, result);
734
735 if (!expected_result) {
736 // Do not check the files if we expect to fail.
737 return;
738 }
739
740 std::string code_path_cur_prof = create_current_profile_path(
741 kTestUserId, package_name, profile_name, /*is_secondary_dex*/ false);
742 std::string code_path_ref_profile = create_reference_profile_path(package_name,
743 profile_name, /*is_secondary_dex*/ false);
744
745 // Check that we created the current profile.
746 CheckFileAccess(code_path_cur_prof, kTestAppUid, kTestAppUid, 0600 | S_IFREG);
747
748 // Without dex metadata we don't generate a reference profile.
749 ASSERT_EQ(-1, access(code_path_ref_profile.c_str(), R_OK));
750 }
751
Calin Juravle0d0a4922018-01-23 19:54:11 -0800752 protected:
Calin Juravle29591732017-11-20 17:46:19 -0800753 void TransitionToSystemServer() {
754 ASSERT_TRUE(DropCapabilities(kSystemUid, kSystemGid));
755 int32_t res = selinux_android_setcontext(
756 kSystemUid, true, se_info_.c_str(), "system_server");
757 ASSERT_EQ(0, res) << "Failed to setcon " << strerror(errno);
758 }
759
760 bool AreFilesEqual(const std::string& file1, const std::string& file2) {
761 std::vector<uint8_t> content1;
762 std::vector<uint8_t> content2;
763
764 if (!ReadAll(file1, &content1)) return false;
765 if (!ReadAll(file2, &content2)) return false;
766 return content1 == content2;
767 }
768
769 bool ReadAll(const std::string& file, std::vector<uint8_t>* content) {
770 unique_fd fd(open(file.c_str(), O_RDONLY));
771 if (fd < 0) {
772 PLOG(ERROR) << "Failed to open " << file;
773 return false;
774 }
775 struct stat st;
776 if (fstat(fd, &st) != 0) {
777 PLOG(ERROR) << "Failed to stat " << file;
778 return false;
779 }
780 content->resize(st.st_size);
781 bool result = ReadFully(fd, content->data(), content->size());
782 if (!result) {
783 PLOG(ERROR) << "Failed to read " << file;
784 }
785 return result;
786 }
787};
788
789TEST_F(ProfileTest, ProfileSnapshotOk) {
790 LOG(INFO) << "ProfileSnapshotOk";
791
792 SetupProfiles(/*setup_ref*/ true);
Calin Juravlec3596c32017-12-05 12:29:15 -0800793 createProfileSnapshot(kTestAppId, package_name_, /*expected_result*/ true);
Calin Juravle29591732017-11-20 17:46:19 -0800794}
795
796// The reference profile is created on the fly. We need to be able to
797// snapshot without one.
798TEST_F(ProfileTest, ProfileSnapshotOkNoReference) {
799 LOG(INFO) << "ProfileSnapshotOkNoReference";
800
801 SetupProfiles(/*setup_ref*/ false);
Calin Juravlec3596c32017-12-05 12:29:15 -0800802 createProfileSnapshot(kTestAppId, package_name_, /*expected_result*/ true);
Calin Juravle29591732017-11-20 17:46:19 -0800803}
804
805TEST_F(ProfileTest, ProfileSnapshotFailWrongPackage) {
806 LOG(INFO) << "ProfileSnapshotFailWrongPackage";
807
808 SetupProfiles(/*setup_ref*/ true);
Calin Juravlec3596c32017-12-05 12:29:15 -0800809 createProfileSnapshot(kTestAppId, "not.there", /*expected_result*/ false);
Calin Juravle29591732017-11-20 17:46:19 -0800810}
811
812TEST_F(ProfileTest, ProfileSnapshotDestroySnapshot) {
813 LOG(INFO) << "ProfileSnapshotDestroySnapshot";
814
815 SetupProfiles(/*setup_ref*/ true);
Calin Juravlec3596c32017-12-05 12:29:15 -0800816 createProfileSnapshot(kTestAppId, package_name_, /*expected_result*/ true);
Calin Juravle29591732017-11-20 17:46:19 -0800817
Calin Juravle824a64d2018-01-18 20:23:17 -0800818 binder::Status binder_result = service_->destroyProfileSnapshot(package_name_, kPrimaryProfile);
Calin Juravle29591732017-11-20 17:46:19 -0800819 ASSERT_TRUE(binder_result.isOk());
820 struct stat st;
821 ASSERT_EQ(-1, stat(snap_profile_.c_str(), &st));
822 ASSERT_EQ(ENOENT, errno);
823}
824
Calin Juravle824a64d2018-01-18 20:23:17 -0800825TEST_F(ProfileTest, ProfileMergeOk) {
826 LOG(INFO) << "ProfileMergeOk";
827
828 SetupProfiles(/*setup_ref*/ true);
Calin Juravle408cd4a2018-01-20 23:34:18 -0800829 mergePackageProfiles(package_name_, "primary.prof", /*expected_result*/ true);
Calin Juravle824a64d2018-01-18 20:23:17 -0800830}
831
832// The reference profile is created on the fly. We need to be able to
833// merge without one.
834TEST_F(ProfileTest, ProfileMergeOkNoReference) {
835 LOG(INFO) << "ProfileMergeOkNoReference";
836
837 SetupProfiles(/*setup_ref*/ false);
Calin Juravle408cd4a2018-01-20 23:34:18 -0800838 mergePackageProfiles(package_name_, "primary.prof", /*expected_result*/ true);
Calin Juravle824a64d2018-01-18 20:23:17 -0800839}
840
841TEST_F(ProfileTest, ProfileMergeFailWrongPackage) {
842 LOG(INFO) << "ProfileMergeFailWrongPackage";
843
844 SetupProfiles(/*setup_ref*/ true);
Calin Juravle408cd4a2018-01-20 23:34:18 -0800845 mergePackageProfiles("not.there", "primary.prof", /*expected_result*/ false);
Calin Juravle824a64d2018-01-18 20:23:17 -0800846}
847
Calin Juravled2affb82017-11-28 17:41:43 -0800848TEST_F(ProfileTest, ProfileDirOk) {
849 LOG(INFO) << "ProfileDirOk";
850
851 std::string cur_profile_dir = create_primary_current_profile_package_dir_path(
852 kTestUserId, package_name_);
853 std::string cur_profile_file = create_current_profile_path(kTestUserId, package_name_,
Calin Juravle824a64d2018-01-18 20:23:17 -0800854 kPrimaryProfile, /*is_secondary_dex*/false);
Calin Juravled2affb82017-11-28 17:41:43 -0800855 std::string ref_profile_dir = create_primary_reference_profile_package_dir_path(package_name_);
856
857 CheckFileAccess(cur_profile_dir, kTestAppUid, kTestAppUid, 0700 | S_IFDIR);
Calin Juravle6f06eb62017-11-28 18:44:53 -0800858 CheckFileAccess(ref_profile_dir, kSystemUid, kTestAppGid, 0770 | S_IFDIR);
859}
860
861// Verify that the profile directories are fixed up during an upgrade.
862// (The reference profile directory is prepared lazily).
863TEST_F(ProfileTest, ProfileDirOkAfterFixup) {
864 LOG(INFO) << "ProfileDirOkAfterFixup";
865
866 std::string cur_profile_dir = create_primary_current_profile_package_dir_path(
867 kTestUserId, package_name_);
868 std::string cur_profile_file = create_current_profile_path(kTestUserId, package_name_,
Calin Juravle824a64d2018-01-18 20:23:17 -0800869 kPrimaryProfile, /*is_secondary_dex*/false);
Calin Juravle6f06eb62017-11-28 18:44:53 -0800870 std::string ref_profile_dir = create_primary_reference_profile_package_dir_path(package_name_);
871
872 // Simulate a pre-P setup by changing the owner to kTestAppGid and permissions to 0700.
873 ASSERT_EQ(0, chown(ref_profile_dir.c_str(), kTestAppGid, kTestAppGid));
874 ASSERT_EQ(0, chmod(ref_profile_dir.c_str(), 0700));
875
876 // Run createAppData again which will offer to fix-up the profile directories.
877 ASSERT_TRUE(service_->createAppData(
878 volume_uuid_,
879 package_name_,
880 kTestUserId,
881 kAppDataFlags,
882 kTestAppUid,
883 se_info_,
884 kOSdkVersion,
885 &ce_data_inode_).isOk());
886
887 // Check the file access.
888 CheckFileAccess(cur_profile_dir, kTestAppUid, kTestAppUid, 0700 | S_IFDIR);
Calin Juravle6f06eb62017-11-28 18:44:53 -0800889 CheckFileAccess(ref_profile_dir, kSystemUid, kTestAppGid, 0770 | S_IFDIR);
Calin Juravled2affb82017-11-28 17:41:43 -0800890}
891
Calin Juravlec3b049e2018-01-18 22:32:58 -0800892TEST_F(ProfileTest, ProfilePrepareOk) {
893 LOG(INFO) << "ProfilePrepareOk";
894 preparePackageProfile(package_name_, "split.prof", /*expected_result*/ true);
895}
896
897TEST_F(ProfileTest, ProfilePrepareFailInvalidPackage) {
898 LOG(INFO) << "ProfilePrepareFailInvalidPackage";
899 preparePackageProfile("not.there.package", "split.prof", /*expected_result*/ false);
900}
901
902TEST_F(ProfileTest, ProfilePrepareFailProfileChangedUid) {
903 LOG(INFO) << "ProfilePrepareFailProfileChangedUid";
904 SetupProfiles(/*setup_ref*/ false);
905 // Change the uid on the profile to trigger a failure.
906 ::chown(cur_profile_.c_str(), kTestAppUid + 1, kTestAppGid + 1);
907 preparePackageProfile(package_name_, "primary.prof", /*expected_result*/ false);
908}
909
Calin Juravle0d0a4922018-01-23 19:54:11 -0800910
911class BootProfileTest : public ProfileTest {
912 public:
913 virtual void setup() {
914 ProfileTest::SetUp();
915 intial_android_profiles_dir = android_profiles_dir;
916 }
917
918 virtual void TearDown() {
919 android_profiles_dir = intial_android_profiles_dir;
920 ProfileTest::TearDown();
921 }
922
923 void UpdateAndroidProfilesDir(const std::string& profile_dir) {
924 android_profiles_dir = profile_dir;
925 // We need to create the reference profile directory in the new profile dir.
926 run_cmd("mkdir -p " + profile_dir + "/ref");
927 }
928
929 void createBootImageProfileSnapshot(const std::string& classpath, bool expected_result) {
930 bool result;
931 binder::Status binder_result = service_->createProfileSnapshot(
932 -1, "android", "android.prof", classpath, &result);
933 ASSERT_TRUE(binder_result.isOk());
934 ASSERT_EQ(expected_result, result);
935
936 if (!expected_result) {
937 // Do not check the files if we expect to fail.
938 return;
939 }
940
941 // Check that the snapshot was created with he expected access flags.
942 const std::string boot_profile = create_snapshot_profile_path("android", "android.prof");
943 CheckFileAccess(boot_profile, kSystemUid, kSystemGid, 0600 | S_IFREG);
944
945 pid_t pid = fork();
946 if (pid == 0) {
947 /* child */
948 TransitionToSystemServer();
949
950 // System server should be able to open the snapshot.
951 unique_fd fd(open(boot_profile.c_str(), O_RDONLY));
952 ASSERT_TRUE(fd > -1) << "Failed to open profile as kSystemUid: " << strerror(errno);
953 _exit(0);
954 }
955 /* parent */
956 ASSERT_TRUE(WIFEXITED(wait_child(pid)));
957 }
958 protected:
959 std::string intial_android_profiles_dir;
960};
961
962TEST_F(BootProfileTest, BootProfileSnapshotOk) {
963 LOG(INFO) << "BootProfileSnapshotOk";
964 char* boot_classpath = getenv("BOOTCLASSPATH");
965 ASSERT_TRUE(boot_classpath != nullptr);
966 createBootImageProfileSnapshot(boot_classpath, /*expected_result*/ true);
967}
968
969TEST_F(BootProfileTest, BootProfileSnapshotFailEmptyClasspath) {
970 LOG(INFO) << "BootProfileSnapshotFailEmptyClasspath";
971
972 createBootImageProfileSnapshot(/*boot_classpath*/ "", /*expected_result*/ false);
973}
974
975TEST_F(BootProfileTest, BootProfileSnapshotOkNoProfiles) {
976 LOG(INFO) << "BootProfileSnapshotOkNoProfiles";
977 char* boot_classpath = getenv("BOOTCLASSPATH");
978 ASSERT_TRUE(boot_classpath != nullptr);
979
980 // The app_apk_dir has no profiles. So we shouldn't be able to merge anything.
981 // Still, this is not a failure case.
982 UpdateAndroidProfilesDir(app_apk_dir_);
983 createBootImageProfileSnapshot(boot_classpath, /*expected_result*/ true);
984}
985
986// Verify that profile collection.
987TEST_F(BootProfileTest, CollectProfiles) {
988 LOG(INFO) << "CollectProfiles";
989
990 // Create some profile directories mimicking the real profile structure.
991 run_cmd("mkdir -p " + app_private_dir_de_ + "/profiles/ref");
992 run_cmd("mkdir -p " + app_private_dir_de_ + "/profiles/cur/0/");
993 run_cmd("mkdir -p " + app_private_dir_de_ + "/profiles/cur/1/");
994 // Create an empty profile.
995 run_cmd("touch " + app_private_dir_de_ + "/profiles/cur/1/primary.prof");
996 // Create a random file.
997 run_cmd("touch " + app_private_dir_de_ + "/profiles/cur/0/non.profile.file");
998
999 // Create some non-empty profiles.
1000 std::string current_prof = app_private_dir_de_ + "/profiles/cur/0/primary.prof";
1001 run_cmd("echo 1 > " + current_prof);
1002 std::string ref_prof = app_private_dir_de_ + "/profiles/ref/primary.prof";
1003 run_cmd("echo 1 > " + ref_prof);
1004
1005 UpdateAndroidProfilesDir(app_private_dir_de_ + "/profiles");
1006
1007 std::vector<std::string> profiles;
1008 collect_profiles(&profiles);
1009
1010 // Only two profiles should be in the output.
1011 ASSERT_EQ(2u, profiles.size());
1012 ASSERT_TRUE(std::find(profiles.begin(), profiles.end(), current_prof) != profiles.end());
1013 ASSERT_TRUE(std::find(profiles.begin(), profiles.end(), ref_prof) != profiles.end());
1014}
1015
Calin Juravle7d765462017-09-04 15:57:10 -07001016} // namespace installd
1017} // namespace android