installd_dexopt_test.cpp revision d2affb8601630fe682b03407fc907f2439ff5370
17d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle/*
27d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle * Copyright (C) 2017 The Android Open Source Project
37d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle *
47d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle * Licensed under the Apache License, Version 2.0 (the "License");
57d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle * you may not use this file except in compliance with the License.
67d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle * You may obtain a copy of the License at
77d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle *
87d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle *      http://www.apache.org/licenses/LICENSE-2.0
97d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle *
107d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle * Unless required by applicable law or agreed to in writing, software
117d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle * distributed under the License is distributed on an "AS IS" BASIS,
127d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle * See the License for the specific language governing permissions and
147d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle * limitations under the License.
157d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle */
167d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
1729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle#include <fcntl.h>
187d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle#include <stdlib.h>
197d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle#include <string.h>
2029591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle#include <sys/types.h>
2129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle#include <sys/stat.h>
227d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
2329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle#include <android-base/file.h>
247d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle#include <android-base/logging.h>
257d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle#include <android-base/stringprintf.h>
2629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle#include <android-base/unique_fd.h>
2729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
287d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle#include <cutils/properties.h>
2929591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
307d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle#include <gtest/gtest.h>
317d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
3229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle#include <selinux/android.h>
3329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle#include <selinux/avc.h>
3429591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
357d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle#include "dexopt.h"
367d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle#include "InstalldNativeService.h"
377d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle#include "globals.h"
387d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle#include "tests/test_utils.h"
397d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle#include "utils.h"
407d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
4129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravleusing android::base::ReadFully;
4229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravleusing android::base::unique_fd;
4329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
447d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravlenamespace android {
457d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravlenamespace installd {
467d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
477d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle// TODO(calin): try to dedup this code.
487d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle#if defined(__arm__)
497d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravlestatic const std::string kRuntimeIsa = "arm";
507d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle#elif defined(__aarch64__)
517d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravlestatic const std::string kRuntimeIsa = "arm64";
527d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle#elif defined(__mips__) && !defined(__LP64__)
537d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravlestatic const std::string kRuntimeIsa = "mips";
547d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle#elif defined(__mips__) && defined(__LP64__)
557d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravlestatic const std::string kRuntimeIsa = "mips64";
567d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle#elif defined(__i386__)
577d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravlestatic const std::string kRuntimeIsa = "x86";
587d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle#elif defined(__x86_64__)
597d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravlestatic const std::string kRuntimeIsa = "x86_64";
607d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle#else
617d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravlestatic const std::string kRuntimeIsa = "none";
627d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle#endif
637d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
647d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravleint get_property(const char *key, char *value, const char *default_value) {
657d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    return property_get(key, value, default_value);
667d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}
677d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
687d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravlebool calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
697d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        const char *instruction_set) {
707d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    return calculate_oat_file_path_default(path, oat_dir, apk_path, instruction_set);
717d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}
727d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
737d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravlebool calculate_odex_file_path(char path[PKG_PATH_MAX], const char *apk_path,
747d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        const char *instruction_set) {
757d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    return calculate_odex_file_path_default(path, apk_path, instruction_set);
767d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}
777d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
787d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravlebool create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *instruction_set) {
797d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    return create_cache_path_default(path, src, instruction_set);
807d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}
817d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
827d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravlestatic void run_cmd(const std::string& cmd) {
837d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    system(cmd.c_str());
847d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}
857d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
867d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravlestatic void mkdir(const std::string& path, uid_t owner, gid_t group, mode_t mode) {
877d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    ::mkdir(path.c_str(), mode);
887d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    ::chown(path.c_str(), owner, group);
897d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    ::chmod(path.c_str(), mode);
907d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}
917d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
9229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravlestatic int log_callback(int type, const char *fmt, ...) { // NOLINT
9329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    va_list ap;
9429591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    int priority;
9529591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
9629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    switch (type) {
9729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        case SELINUX_WARNING:
9829591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle            priority = ANDROID_LOG_WARN;
9929591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle            break;
10029591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        case SELINUX_INFO:
10129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle            priority = ANDROID_LOG_INFO;
10229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle            break;
10329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        default:
10429591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle            priority = ANDROID_LOG_ERROR;
10529591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle            break;
10629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    }
10729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    va_start(ap, fmt);
10829591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    LOG_PRI_VA(priority, "SELinux", fmt, ap);
10929591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    va_end(ap);
11029591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    return 0;
11129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle}
11229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
11329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravlestatic bool init_selinux() {
11429591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    int selinux_enabled = (is_selinux_enabled() > 0);
11529591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
11629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    union selinux_callback cb;
11729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    cb.func_log = log_callback;
11829591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    selinux_set_callback(SELINUX_CB_LOG, cb);
11929591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
12029591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    if (selinux_enabled && selinux_status_open(true) < 0) {
12129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        LOG(ERROR) << "Could not open selinux status; exiting";
12229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        return false;
12329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    }
12429591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
12529591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    return true;
12629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle}
12729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
1287d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle// Base64 encoding of a simple dex files with 2 methods.
1297d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravlestatic const char kDexFile[] =
1307d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    "UEsDBBQAAAAIAOiOYUs9y6BLCgEAABQCAAALABwAY2xhc3Nlcy5kZXhVVAkAA/Ns+lkOHv1ZdXgL"
1317d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    "AAEEI+UCAASIEwAAS0mt4DIwNmX4qpn7j/2wA7v7N+ZvoQpCJRlVx5SWa4YaiDAxMBQwMDBUhJkI"
1327d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    "MUBBDyMDAzsDRJwFxAdioBDDHAYEYAbiFUAM1M5wAIhFGCGKDIDYAogdgNgDiH2BOAiI0xghekDm"
1337d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    "sQIxGxQzM6ACRijNhCbOhCZfyohdPYyuh8szgtVkMkLsLhAAqeCDi+ejibPZZOZlltgxsDnqZSWW"
1347d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    "JTKwOUFoZh9HayDhZM0g5AMS0M9JzEvX90/KSk0usWZgDAMaws5nAyXBzmpoYGlgAjsAyJoBMp0b"
1357d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    "zQ8gGhbOTEhhzYwU3qxIYc2GFN6MClC/AhUyKUDMAYU9M1Qc5F8GKBscVgIQM0FxCwBQSwECHgMU"
1367d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    "AAAACADojmFLPcugSwoBAAAUAgAACwAYAAAAAAAAAAAAoIEAAAAAY2xhc3Nlcy5kZXhVVAUAA/Ns"
1377d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    "+ll1eAsAAQQj5QIABIgTAABQSwUGAAAAAAEAAQBRAAAATwEAAAAA";
1387d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
1397d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
1407d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravleclass DexoptTest : public testing::Test {
1417d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravleprotected:
1427d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    static constexpr bool kDebug = false;
1437d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    static constexpr uid_t kSystemUid = 1000;
1447d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    static constexpr uid_t kSystemGid = 1000;
1457d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    static constexpr int32_t kOSdkVersion = 25;
1467d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    static constexpr int32_t kAppDataFlags = FLAG_STORAGE_CE | FLAG_STORAGE_DE;
1477d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    static constexpr int32_t kTestUserId = 0;
148d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle    static constexpr uid_t kTestAppId = 19999;
149d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle
150d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle    const gid_t kTestAppUid = multiuser_get_uid(kTestUserId, kTestAppId);
151d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle    const uid_t kTestAppGid = multiuser_get_shared_gid(kTestUserId, kTestAppId);
1527d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
1537d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    InstalldNativeService* service_;
1547d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    std::unique_ptr<std::string> volume_uuid_;
1557d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    std::string package_name_;
1567d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    std::string app_apk_dir_;
1577d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    std::string app_private_dir_ce_;
1587d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    std::string app_private_dir_de_;
1597d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    std::string se_info_;
1607d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
1617d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    int64_t ce_data_inode_;
1627d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
1637d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    std::string secondary_dex_ce_;
1647d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    std::string secondary_dex_ce_link_;
1657d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    std::string secondary_dex_de_;
1667d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
1677d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    virtual void SetUp() {
1687d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        setenv("ANDROID_LOG_TAGS", "*:v", 1);
1697d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        android::base::InitLogging(nullptr);
17029591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        // Initialize the globals holding the file system main paths (/data/, /system/ etc..).
17129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        // This is needed in order to compute the application and profile paths.
17229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        ASSERT_TRUE(init_globals_from_data_and_root());
17329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        // Initialize selinux log callbacks.
17429591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        // This ensures that selinux is up and running and re-directs the selinux messages
17529591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        // to logcat (in order to make it easier to investigate test results).
17629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        ASSERT_TRUE(init_selinux());
1777d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        service_ = new InstalldNativeService();
1787d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
1797d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        volume_uuid_ = nullptr;
1807d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        package_name_ = "com.installd.test.dexopt";
1817d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        se_info_ = "default";
1827d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        app_apk_dir_ = android_app_dir + package_name_;
1837d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
1847d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        create_mock_app();
1857d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    }
1867d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
1877d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    virtual void TearDown() {
1887d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        if (!kDebug) {
1897d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            service_->destroyAppData(
1907d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle                volume_uuid_, package_name_, kTestUserId, kAppDataFlags, ce_data_inode_);
1917d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            run_cmd("rm -rf " + app_apk_dir_);
1927d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            run_cmd("rm -rf " + app_private_dir_ce_);
1937d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            run_cmd("rm -rf " + app_private_dir_de_);
1947d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        }
1957d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        delete service_;
1967d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    }
1977d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
1987d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    void create_mock_app() {
1997d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        // Create the oat dir.
2007d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        std::string app_oat_dir = app_apk_dir_ + "/oat";
2017d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        mkdir(app_apk_dir_, kSystemUid, kSystemGid, 0755);
2027d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        service_->createOatDir(app_oat_dir, kRuntimeIsa);
2037d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
2047d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        // Copy the primary apk.
2057d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        std::string apk_path = app_apk_dir_ + "/base.jar";
2067d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        ASSERT_TRUE(WriteBase64ToFile(kDexFile, apk_path, kSystemUid, kSystemGid, 0644));
2077d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
2087d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        // Create the app user data.
2097d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        ASSERT_TRUE(service_->createAppData(
2107d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            volume_uuid_,
2117d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            package_name_,
2127d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            kTestUserId,
2137d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            kAppDataFlags,
2147d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            kTestAppUid,
2157d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            se_info_,
2167d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            kOSdkVersion,
2177d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            &ce_data_inode_).isOk());
2187d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
2197d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        // Create a secondary dex file on CE storage
2207d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        const char* volume_uuid_cstr = volume_uuid_ == nullptr ? nullptr : volume_uuid_->c_str();
2217d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        app_private_dir_ce_ = create_data_user_ce_package_path(
2227d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle                volume_uuid_cstr, kTestUserId, package_name_.c_str());
2237d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        secondary_dex_ce_ = app_private_dir_ce_ + "/secondary_ce.jar";
2247d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        ASSERT_TRUE(WriteBase64ToFile(kDexFile, secondary_dex_ce_, kTestAppUid, kTestAppGid, 0600));
2257d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        std::string app_private_dir_ce_link = create_data_user_ce_package_path_as_user_link(
2267d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle                volume_uuid_cstr, kTestUserId, package_name_.c_str());
2277d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        secondary_dex_ce_link_ = app_private_dir_ce_link + "/secondary_ce.jar";
2287d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
2297d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        // Create a secondary dex file on DE storage.
2307d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        app_private_dir_de_ = create_data_user_de_package_path(
2317d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle                volume_uuid_cstr, kTestUserId, package_name_.c_str());
2327d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        secondary_dex_de_ = app_private_dir_de_ + "/secondary_de.jar";
2337d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        ASSERT_TRUE(WriteBase64ToFile(kDexFile, secondary_dex_de_, kTestAppUid, kTestAppGid, 0600));
2347d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
2357d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        // Fix app data uid.
2367d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        ASSERT_TRUE(service_->fixupAppData(volume_uuid_, kTestUserId).isOk());
2377d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    }
2387d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
2397d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
24029591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    std::string GetSecondaryDexArtifact(const std::string& path, const std::string& type) {
2417d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        std::string::size_type end = path.rfind('.');
2427d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        std::string::size_type start = path.rfind('/', end);
2437d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        return path.substr(0, start) + "/oat/" + kRuntimeIsa + "/" +
2447d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle                path.substr(start + 1, end - start) + type;
2457d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    }
2467d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
24729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    void CompileSecondaryDex(const std::string& path, int32_t dex_storage_flag,
2487d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            bool should_binder_call_succeed, bool should_dex_be_compiled = true,
249d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle            int32_t uid = -1) {
250d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle        if (uid == -1) {
251d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle            uid = kTestAppUid;
252d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle        }
2537d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        std::unique_ptr<std::string> package_name_ptr(new std::string(package_name_));
2547d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        int32_t dexopt_needed = 0;  // does not matter;
2557d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        std::unique_ptr<std::string> out_path = nullptr;  // does not matter
2567d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        int32_t dex_flags = DEXOPT_SECONDARY_DEX | dex_storage_flag;
2577d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        std::string compiler_filter = "speed-profile";
2587d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        std::unique_ptr<std::string> class_loader_context_ptr(new std::string("&"));
2597d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        std::unique_ptr<std::string> se_info_ptr(new std::string(se_info_));
2607d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        bool downgrade = false;
2617d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
2627d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        binder::Status result = service_->dexopt(path,
2637d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle                                                 uid,
2647d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle                                                 package_name_ptr,
2657d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle                                                 kRuntimeIsa,
2667d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle                                                 dexopt_needed,
2677d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle                                                 out_path,
2687d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle                                                 dex_flags,
2697d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle                                                 compiler_filter,
2707d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle                                                 volume_uuid_,
2717d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle                                                 class_loader_context_ptr,
2727d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle                                                 se_info_ptr,
2737d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle                                                 downgrade);
2747d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        ASSERT_EQ(should_binder_call_succeed, result.isOk());
2757d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        int expected_access = should_dex_be_compiled ? 0 : -1;
27629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        std::string odex = GetSecondaryDexArtifact(path, "odex");
27729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        std::string vdex = GetSecondaryDexArtifact(path, "vdex");
27829591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        std::string art = GetSecondaryDexArtifact(path, "art");
2797d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        ASSERT_EQ(expected_access, access(odex.c_str(), R_OK));
2807d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        ASSERT_EQ(expected_access, access(vdex.c_str(), R_OK));
2817d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        ASSERT_EQ(-1, access(art.c_str(), R_OK));  // empty profiles do not generate an image.
2827d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    }
2837d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
2847d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    void reconcile_secondary_dex(const std::string& path, int32_t storage_flag,
2857d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            bool should_binder_call_succeed, bool should_dex_exist, bool should_dex_be_deleted,
286d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle            int32_t uid = -1, std::string* package_override = nullptr) {
287d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle        if (uid == -1) {
288d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle            uid = kTestAppUid;
289d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle        }
2907d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        std::vector<std::string> isas;
2917d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        isas.push_back(kRuntimeIsa);
2927d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        bool out_secondary_dex_exists = false;
2937d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        binder::Status result = service_->reconcileSecondaryDexFile(
2947d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            path,
2957d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            package_override == nullptr ? package_name_ : *package_override,
2967d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            uid,
2977d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            isas,
2987d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            volume_uuid_,
2997d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            storage_flag,
3007d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            &out_secondary_dex_exists);
3017d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
3027d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        ASSERT_EQ(should_binder_call_succeed, result.isOk());
3037d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        ASSERT_EQ(should_dex_exist, out_secondary_dex_exists);
3047d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
3057d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        int expected_access = should_dex_be_deleted ? -1 : 0;
30629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        std::string odex = GetSecondaryDexArtifact(path, "odex");
30729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        std::string vdex = GetSecondaryDexArtifact(path, "vdex");
30829591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        std::string art = GetSecondaryDexArtifact(path, "art");
3097d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        ASSERT_EQ(expected_access, access(odex.c_str(), F_OK));
3107d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        ASSERT_EQ(expected_access, access(vdex.c_str(), F_OK));
3117d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        ASSERT_EQ(-1, access(art.c_str(), R_OK));  // empty profiles do not generate an image.
3127d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    }
31329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
31429591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    void CheckFileAccess(const std::string& file, uid_t uid, gid_t gid, mode_t mode) {
31529591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        struct stat st;
31629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        ASSERT_EQ(0, stat(file.c_str(), &st));
31729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        ASSERT_EQ(uid, st.st_uid);
31829591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        ASSERT_EQ(gid, st.st_gid);
31929591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        ASSERT_EQ(mode, st.st_mode);
32029591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    }
3217d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle};
3227d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
3237d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
3247d7654646abb84bbae6b245de270ac087cdc8a95Calin JuravleTEST_F(DexoptTest, DexoptSecondaryCe) {
3257d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    LOG(INFO) << "DexoptSecondaryCe";
32629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE,
3277d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        /*binder_ok*/ true, /*compile_ok*/ true);
3287d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}
3297d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
3307d7654646abb84bbae6b245de270ac087cdc8a95Calin JuravleTEST_F(DexoptTest, DexoptSecondaryCeLink) {
3317d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    LOG(INFO) << "DexoptSecondaryCeLink";
33229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    CompileSecondaryDex(secondary_dex_ce_link_, DEXOPT_STORAGE_CE,
3337d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        /*binder_ok*/ true, /*compile_ok*/ true);
3347d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}
3357d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
3367d7654646abb84bbae6b245de270ac087cdc8a95Calin JuravleTEST_F(DexoptTest, DexoptSecondaryDe) {
3377d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    LOG(INFO) << "DexoptSecondaryDe";
33829591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    CompileSecondaryDex(secondary_dex_de_, DEXOPT_STORAGE_DE,
3397d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        /*binder_ok*/ true, /*compile_ok*/ true);
3407d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}
3417d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
3427d7654646abb84bbae6b245de270ac087cdc8a95Calin JuravleTEST_F(DexoptTest, DexoptSecondaryDoesNotExist) {
3437d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    LOG(INFO) << "DexoptSecondaryDoesNotExist";
3447d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    // If the file validates but does not exist we do not treat it as an error.
34529591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    CompileSecondaryDex(secondary_dex_ce_ + "not.there", DEXOPT_STORAGE_CE,
3467d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        /*binder_ok*/ true,  /*compile_ok*/ false);
3477d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}
3487d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
3497d7654646abb84bbae6b245de270ac087cdc8a95Calin JuravleTEST_F(DexoptTest, DexoptSecondaryStorageValidationError) {
3507d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    LOG(INFO) << "DexoptSecondaryStorageValidationError";
35129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_DE,
3527d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        /*binder_ok*/ false,  /*compile_ok*/ false);
3537d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}
3547d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
3557d7654646abb84bbae6b245de270ac087cdc8a95Calin JuravleTEST_F(DexoptTest, DexoptSecondaryAppOwnershipValidationError) {
3567d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    LOG(INFO) << "DexoptSecondaryAppOwnershipValidationError";
35729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    CompileSecondaryDex("/data/data/random.app/secondary.jar", DEXOPT_STORAGE_CE,
3587d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        /*binder_ok*/ false,  /*compile_ok*/ false);
3597d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}
3607d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
3617d7654646abb84bbae6b245de270ac087cdc8a95Calin JuravleTEST_F(DexoptTest, DexoptSecondaryAcessViaDifferentUidError) {
3627d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    LOG(INFO) << "DexoptSecondaryAcessViaDifferentUidError";
36329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE,
3647d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        /*binder_ok*/ false,  /*compile_ok*/ false, kSystemUid);
3657d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}
3667d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
3677d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
3687d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravleclass ReconcileTest : public DexoptTest {
3697d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    virtual void SetUp() {
3707d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        DexoptTest::SetUp();
37129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE,
3727d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            /*binder_ok*/ true, /*compile_ok*/ true);
37329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        CompileSecondaryDex(secondary_dex_de_, DEXOPT_STORAGE_DE,
3747d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle            /*binder_ok*/ true, /*compile_ok*/ true);
3757d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    }
3767d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle};
3777d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
3787d7654646abb84bbae6b245de270ac087cdc8a95Calin JuravleTEST_F(ReconcileTest, ReconcileSecondaryCeExists) {
3797d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    LOG(INFO) << "ReconcileSecondaryCeExists";
3807d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_CE,
3817d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        /*binder_ok*/ true, /*dex_ok */ true, /*odex_deleted*/ false);
3827d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}
3837d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
3847d7654646abb84bbae6b245de270ac087cdc8a95Calin JuravleTEST_F(ReconcileTest, ReconcileSecondaryCeLinkExists) {
3857d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    LOG(INFO) << "ReconcileSecondaryCeLinkExists";
3867d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    reconcile_secondary_dex(secondary_dex_ce_link_, FLAG_STORAGE_CE,
3877d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        /*binder_ok*/ true, /*dex_ok */ true, /*odex_deleted*/ false);
3887d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}
3897d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
3907d7654646abb84bbae6b245de270ac087cdc8a95Calin JuravleTEST_F(ReconcileTest, ReconcileSecondaryDeExists) {
3917d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    LOG(INFO) << "ReconcileSecondaryDeExists";
3927d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    reconcile_secondary_dex(secondary_dex_de_, FLAG_STORAGE_DE,
3937d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        /*binder_ok*/ true, /*dex_ok */ true, /*odex_deleted*/ false);
3947d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}
3957d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
3967d7654646abb84bbae6b245de270ac087cdc8a95Calin JuravleTEST_F(ReconcileTest, ReconcileSecondaryDeDoesNotExist) {
3977d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    LOG(INFO) << "ReconcileSecondaryDeDoesNotExist";
3987d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    run_cmd("rm -rf " + secondary_dex_de_);
3997d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    reconcile_secondary_dex(secondary_dex_de_, FLAG_STORAGE_DE,
4007d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ true);
4017d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}
4027d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
4037d7654646abb84bbae6b245de270ac087cdc8a95Calin JuravleTEST_F(ReconcileTest, ReconcileSecondaryStorageValidationError) {
4047d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    // Validation errors will not clean the odex/vdex/art files but will mark
4057d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    // the file as non existent so that the PM knows it should purge it from its
4067d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    // records.
4077d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    LOG(INFO) << "ReconcileSecondaryStorageValidationError";
4087d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_DE,
4097d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ false);
4107d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}
4117d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
4127d7654646abb84bbae6b245de270ac087cdc8a95Calin JuravleTEST_F(ReconcileTest, ReconcileSecondaryAppOwnershipValidationError) {
4137d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    LOG(INFO) << "ReconcileSecondaryAppOwnershipValidationError";
4147d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    // Attempt to reconcile the dex files of the test app from a different app.
4157d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    std::string another_app = "another.app";
4167d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_CE,
4177d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ false, kSystemUid, &another_app);
4187d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}
4197d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
4207d7654646abb84bbae6b245de270ac087cdc8a95Calin JuravleTEST_F(ReconcileTest, ReconcileSecondaryAcessViaDifferentUidError) {
4217d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    LOG(INFO) << "ReconcileSecondaryAcessViaDifferentUidError";
4227d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle    reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_CE,
4237d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle        /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ false, kSystemUid);
4247d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}
4257d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle
42629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravleclass ProfileTest : public DexoptTest {
42729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle  protected:
42829591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    std::string cur_profile_;
42929591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    std::string ref_profile_;
43029591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    std::string snap_profile_;
43129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
43229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    virtual void SetUp() {
43329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        DexoptTest::SetUp();
43429591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        cur_profile_ = create_current_profile_path(
43529591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle                kTestUserId, package_name_, /*is_secondary_dex*/ false);
43629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        ref_profile_ = create_reference_profile_path(package_name_, /*is_secondary_dex*/ false);
43729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        snap_profile_ = create_snapshot_profile_path(package_name_, "base.jar");
43829591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    }
43929591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
44029591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    void SetupProfile(const std::string& path, uid_t uid, gid_t gid, mode_t mode, int32_t seed) {
44129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        run_cmd("profman --generate-test-profile-seed=" + std::to_string(seed) +
44229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle                " --generate-test-profile-num-dex=2 --generate-test-profile=" + path);
44329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        ::chmod(path.c_str(), mode);
44429591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        ::chown(path.c_str(), uid, gid);
44529591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    }
44629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
44729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    void SetupProfiles(bool setup_ref) {
44829591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        SetupProfile(cur_profile_, kTestAppUid, kTestAppGid, 0600, 1);
44929591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        if (setup_ref) {
45029591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle            SetupProfile(ref_profile_, kTestAppUid, kTestAppGid, 0060, 2);
45129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        }
45229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    }
45329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
45429591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    void SnapshotProfile(int32_t appid, const std::string& package_name, bool expected_result) {
45529591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        bool result;
45629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        binder::Status binder_result = service_->snapshotProfile(
45729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle                appid, package_name, "base.jar", &result);
45829591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        ASSERT_TRUE(binder_result.isOk());
45929591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        ASSERT_EQ(expected_result, result);
46029591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
46129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        if (!expected_result) {
46229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle            // Do not check the files if we expect to fail.
46329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle            return;
46429591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        }
46529591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
46629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        // Check that the snapshot was created witht he expected acess flags.
46729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        CheckFileAccess(snap_profile_, kSystemUid, kSystemGid, 0600 | S_IFREG);
46829591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
46929591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        // The snapshot should be equivalent to the merge of profiles.
47029591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        std::string expected_profile_content = snap_profile_ + ".expected";
47129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        run_cmd("rm -f " + expected_profile_content);
47229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        run_cmd("touch " + expected_profile_content);
47329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        run_cmd("profman --profile-file=" + cur_profile_ +
47429591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle                " --profile-file=" + ref_profile_ +
47529591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle                " --reference-profile-file=" + expected_profile_content);
47629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
47729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        ASSERT_TRUE(AreFilesEqual(expected_profile_content, snap_profile_));
47829591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
47929591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        pid_t pid = fork();
48029591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        if (pid == 0) {
48129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle            /* child */
48229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle            TransitionToSystemServer();
48329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
48429591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle            // System server should be able to open the the spanshot.
48529591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle            unique_fd fd(open(snap_profile_.c_str(), O_RDONLY));
48629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle            ASSERT_TRUE(fd > -1) << "Failed to open profile as kSystemUid: " << strerror(errno);
48729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle            _exit(0);
48829591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        }
48929591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        /* parent */
49029591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        ASSERT_TRUE(WIFEXITED(wait_child(pid)));
49129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    }
49229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
49329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle  private:
49429591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    void TransitionToSystemServer() {
49529591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        ASSERT_TRUE(DropCapabilities(kSystemUid, kSystemGid));
49629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        int32_t res = selinux_android_setcontext(
49729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle                kSystemUid, true, se_info_.c_str(), "system_server");
49829591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        ASSERT_EQ(0, res) << "Failed to setcon " << strerror(errno);
49929591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    }
50029591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
50129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    bool AreFilesEqual(const std::string& file1, const std::string& file2) {
50229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        std::vector<uint8_t> content1;
50329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        std::vector<uint8_t> content2;
50429591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
50529591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        if (!ReadAll(file1, &content1)) return false;
50629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        if (!ReadAll(file2, &content2)) return false;
50729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        return content1 == content2;
50829591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    }
50929591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
51029591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    bool ReadAll(const std::string& file, std::vector<uint8_t>* content) {
51129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        unique_fd fd(open(file.c_str(), O_RDONLY));
51229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        if (fd < 0) {
51329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle            PLOG(ERROR) << "Failed to open " << file;
51429591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle            return false;
51529591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        }
51629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        struct stat st;
51729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        if (fstat(fd, &st) != 0) {
51829591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle            PLOG(ERROR) << "Failed to stat " << file;
51929591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle            return false;
52029591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        }
52129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        content->resize(st.st_size);
52229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        bool result = ReadFully(fd, content->data(), content->size());
52329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        if (!result) {
52429591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle            PLOG(ERROR) << "Failed to read " << file;
52529591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        }
52629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle        return result;
52729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    }
52829591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle};
52929591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
53029591736958a7ed45f4b5982ca9a46756baa0f6dCalin JuravleTEST_F(ProfileTest, ProfileSnapshotOk) {
53129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    LOG(INFO) << "ProfileSnapshotOk";
53229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
53329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    SetupProfiles(/*setup_ref*/ true);
53429591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    SnapshotProfile(kTestAppId, package_name_, /*expected_result*/ true);
53529591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle}
53629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
53729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle// The reference profile is created on the fly. We need to be able to
53829591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle// snapshot without one.
53929591736958a7ed45f4b5982ca9a46756baa0f6dCalin JuravleTEST_F(ProfileTest, ProfileSnapshotOkNoReference) {
54029591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    LOG(INFO) << "ProfileSnapshotOkNoReference";
54129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
54229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    SetupProfiles(/*setup_ref*/ false);
54329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    SnapshotProfile(kTestAppId, package_name_, /*expected_result*/ true);
54429591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle}
54529591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
54629591736958a7ed45f4b5982ca9a46756baa0f6dCalin JuravleTEST_F(ProfileTest, ProfileSnapshotFailWrongPackage) {
54729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    LOG(INFO) << "ProfileSnapshotFailWrongPackage";
54829591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
54929591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    SetupProfiles(/*setup_ref*/ true);
55029591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    SnapshotProfile(kTestAppId, "not.there", /*expected_result*/ false);
55129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle}
55229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
55329591736958a7ed45f4b5982ca9a46756baa0f6dCalin JuravleTEST_F(ProfileTest, ProfileSnapshotDestroySnapshot) {
55429591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    LOG(INFO) << "ProfileSnapshotDestroySnapshot";
55529591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
55629591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    SetupProfiles(/*setup_ref*/ true);
55729591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    SnapshotProfile(kTestAppId, package_name_, /*expected_result*/ true);
55829591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
55929591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    binder::Status binder_result = service_->destroyProfileSnapshot(package_name_, "base.jar");
56029591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    ASSERT_TRUE(binder_result.isOk());
56129591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    struct stat st;
56229591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    ASSERT_EQ(-1, stat(snap_profile_.c_str(), &st));
56329591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle    ASSERT_EQ(ENOENT, errno);
56429591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle}
56529591736958a7ed45f4b5982ca9a46756baa0f6dCalin Juravle
566d2affb8601630fe682b03407fc907f2439ff5370Calin JuravleTEST_F(ProfileTest, ProfileDirOk) {
567d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle    LOG(INFO) << "ProfileDirOk";
568d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle
569d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle    std::string cur_profile_dir = create_primary_current_profile_package_dir_path(
570d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle            kTestUserId, package_name_);
571d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle    std::string cur_profile_file = create_current_profile_path(kTestUserId, package_name_,
572d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle            /*is_secondary_dex*/false);
573d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle    std::string ref_profile_dir = create_primary_reference_profile_package_dir_path(package_name_);
574d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle
575d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle    CheckFileAccess(cur_profile_dir, kTestAppUid, kTestAppUid, 0700 | S_IFDIR);
576d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle    CheckFileAccess(cur_profile_file, kTestAppUid, kTestAppUid, 0600 | S_IFREG);
577d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle    CheckFileAccess(ref_profile_dir, kTestAppGid, kTestAppGid, 0701 | S_IFDIR);
578d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle}
579d2affb8601630fe682b03407fc907f2439ff5370Calin Juravle
5807d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}  // namespace installd
5817d7654646abb84bbae6b245de270ac087cdc8a95Calin Juravle}  // namespace android
582