16c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey/*
26c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey * Copyright (C) 2016 The Android Open Source Project
36c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey *
46c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
56c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey * you may not use this file except in compliance with the License.
66c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey * You may obtain a copy of the License at
76c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey *
86c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
96c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey *
106c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
116c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
126c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey * See the License for the specific language governing permissions and
146c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey * limitations under the License.
156c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey */
16a5e161b1207ef447a51e99856097d69d4a6111e1Mark Salyzyn#define LOG_TAG "installed"
176c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey
1890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey#include <fcntl.h>
196c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey#include <stdlib.h>
206c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey#include <string.h>
2190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey#include <sys/capability.h>
2290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey#include <sys/file.h>
236c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey#include <sys/stat.h>
2490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey#include <sys/time.h>
2590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey#include <sys/types.h>
2690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey#include <sys/resource.h>
2790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey#include <sys/wait.h>
286c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey#include <unistd.h>
296c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey
306c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey#include <android-base/logging.h>
316c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey#include <android-base/stringprintf.h>
3290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey#include <android-base/strings.h>
3390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey#include <android-base/unique_fd.h>
3480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle#include <cutils/fs.h>
3590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey#include <cutils/properties.h>
3690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey#include <cutils/sched_policy.h>
377823e124e00576e20e47ec717cbe8bc89f0f2bf2Mark Salyzyn#include <log/log.h>               // TODO: Move everything to base/logging.
3890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey#include <private/android_filesystem_config.h>
39cb556e340b50d16e8fac41b0c69d8d35bd7915f9Calin Juravle#include <selinux/android.h>
4090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey#include <system/thread_defs.h>
416c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey
426c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey#include "dexopt.h"
4390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey#include "installd_deps.h"
4490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey#include "otapreopt_utils.h"
456c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey#include "utils.h"
466c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey
476c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkeyusing android::base::StringPrintf;
4890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeyusing android::base::EndsWith;
491a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravleusing android::base::unique_fd;
506c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey
516c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkeynamespace android {
526c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkeynamespace installd {
536c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey
54114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle// Deleter using free() for use with std::unique_ptr<>. See also UniqueCPtr<> below.
55114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravlestruct FreeDelete {
56114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle  // NOTE: Deleting a const object is valid but free() takes a non-const pointer.
57114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle  void operator()(const void* ptr) const {
58114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    free(const_cast<void*>(ptr));
59114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle  }
60114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle};
61114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle
62114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle// Alias for std::unique_ptr<> that uses the C function free() to delete objects.
63114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravletemplate <typename T>
64114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravleusing UniqueCPtr = std::unique_ptr<T, FreeDelete>;
65114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle
661a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravlestatic unique_fd invalid_unique_fd() {
671a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle    return unique_fd(-1);
681a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle}
691a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle
7090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic bool clear_profile(const std::string& profile) {
711a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle    unique_fd ufd(open(profile.c_str(), O_WRONLY | O_NOFOLLOW | O_CLOEXEC));
7290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (ufd.get() < 0) {
7390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (errno != ENOENT) {
7490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            PLOG(WARNING) << "Could not open profile " << profile;
7590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            return false;
7690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        } else {
7790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            // Nothing to clear. That's ok.
7890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            return true;
7990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
8090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
8190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
8290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (flock(ufd.get(), LOCK_EX | LOCK_NB) != 0) {
8390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (errno != EWOULDBLOCK) {
8490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            PLOG(WARNING) << "Error locking profile " << profile;
8590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
8690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        // This implies that the app owning this profile is running
8790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        // (and has acquired the lock).
8890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        //
8990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        // If we can't acquire the lock bail out since clearing is useless anyway
9090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        // (the app will write again to the profile).
9190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        //
9290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        // Note:
9390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        // This does not impact the this is not an issue for the profiling correctness.
9490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        // In case this is needed because of an app upgrade, profiles will still be
9590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        // eventually cleared by the app itself due to checksum mismatch.
9690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        // If this is needed because profman advised, then keeping the data around
9790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        // until the next run is again not an issue.
9890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        //
9990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        // If the app attempts to acquire a lock while we've held one here,
10090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        // it will simply skip the current write cycle.
10190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return false;
10290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
10390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
10490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool truncated = ftruncate(ufd.get(), 0) == 0;
10590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (!truncated) {
10690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        PLOG(WARNING) << "Could not truncate " << profile;
10790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
10890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (flock(ufd.get(), LOCK_UN) != 0) {
10990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        PLOG(WARNING) << "Error unlocking profile " << profile;
11090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
11190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    return truncated;
11290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
11390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
114114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle// Clear the reference profile for the given location.
115114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle// The location is the package name for primary apks or the dex path for secondary dex files.
116114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravlestatic bool clear_reference_profile(const std::string& location, bool is_secondary_dex) {
117114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    return clear_profile(create_reference_profile_path(location, is_secondary_dex));
11890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
11990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
120114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle// Clear the reference profile for the given location.
121114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle// The location is the package name for primary apks or the dex path for secondary dex files.
122114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravlestatic bool clear_current_profile(const std::string& pkgname, userid_t user,
123114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        bool is_secondary_dex) {
124114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    return clear_profile(create_current_profile_path(user, pkgname, is_secondary_dex));
12590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
12690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
127114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle// Clear the reference profile for the primary apk of the given package.
128114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravlebool clear_primary_reference_profile(const std::string& pkgname) {
129114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    return clear_reference_profile(pkgname, /*is_secondary_dex*/false);
130114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle}
131114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle
132114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle// Clear all current profile for the primary apk of the given package.
133114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravlebool clear_primary_current_profiles(const std::string& pkgname) {
13490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool success = true;
135114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    // For secondary dex files, we don't really need the user but we use it for sanity checks.
13690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
13790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    for (auto user : users) {
138114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        success &= clear_current_profile(pkgname, user, /*is_secondary_dex*/false);
13990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
14090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    return success;
14190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
14290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
143114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle// Clear the current profile for the primary apk of the given package and user.
144114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravlebool clear_primary_current_profile(const std::string& pkgname, userid_t user) {
145114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    return clear_current_profile(pkgname, user, /*is_secondary_dex*/false);
146114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle}
147114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle
14890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic int split_count(const char *str)
14990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey{
15090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  char *ctx;
15190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  int count = 0;
15290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  char buf[kPropertyValueMax];
15390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
15490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  strncpy(buf, str, sizeof(buf));
15590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  char *pBuf = buf;
15690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
15790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  while(strtok_r(pBuf, " ", &ctx) != NULL) {
15890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    count++;
15990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    pBuf = NULL;
16090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  }
16190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
16290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  return count;
16390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
16490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
16590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic int split(char *buf, const char **argv)
16690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey{
16790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  char *ctx;
16890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  int count = 0;
16990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  char *tok;
17090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  char *pBuf = buf;
17190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
17290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  while((tok = strtok_r(pBuf, " ", &ctx)) != NULL) {
17390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    argv[count++] = tok;
17490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    pBuf = NULL;
17590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  }
17690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
17790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  return count;
17890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
17990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
18010b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Haostatic const char* get_location_from_path(const char* path) {
18110b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao    static constexpr char kLocationSeparator = '/';
18210b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao    const char *location = strrchr(path, kLocationSeparator);
18310b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao    if (location == NULL) {
18410b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao        return path;
18510b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao    } else {
18610b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao        // Skip the separator character.
18710b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao        return location + 1;
18810b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao    }
18910b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao}
19010b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao
19190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vdex_fd, int image_fd,
19290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        const char* input_file_name, const char* output_file_name, int swap_fd,
193a0af34de9ef2449000343b468f4a056a91dcdbb6Nicolas Geoffray        const char* instruction_set, const char* compiler_filter,
19490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        bool debuggable, bool post_bootcomplete, int profile_fd, const char* shared_libraries) {
19590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
19690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
19790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
19890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        ALOGE("Instruction set %s longer than max length of %d",
19990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey              instruction_set, MAX_INSTRUCTION_SET_LEN);
20090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return;
20190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
20290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
20310b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao    // Get the relative path to the input file.
20410b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao    const char* relative_input_file_name = get_location_from_path(input_file_name);
20510b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao
20690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    char dex2oat_Xms_flag[kPropertyValueMax];
20790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool have_dex2oat_Xms_flag = get_property("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, NULL) > 0;
20890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
20990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    char dex2oat_Xmx_flag[kPropertyValueMax];
21090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool have_dex2oat_Xmx_flag = get_property("dalvik.vm.dex2oat-Xmx", dex2oat_Xmx_flag, NULL) > 0;
21190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
21290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    char dex2oat_threads_buf[kPropertyValueMax];
21390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool have_dex2oat_threads_flag = get_property(post_bootcomplete
21490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                                                      ? "dalvik.vm.dex2oat-threads"
21590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                                                      : "dalvik.vm.boot-dex2oat-threads",
21690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                                                  dex2oat_threads_buf,
21790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                                                  NULL) > 0;
21890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    char dex2oat_threads_arg[kPropertyValueMax + 2];
21990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (have_dex2oat_threads_flag) {
22090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        sprintf(dex2oat_threads_arg, "-j%s", dex2oat_threads_buf);
22190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
22290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
22390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    char dex2oat_isa_features_key[kPropertyKeyMax];
22490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set);
22590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    char dex2oat_isa_features[kPropertyValueMax];
22690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool have_dex2oat_isa_features = get_property(dex2oat_isa_features_key,
22790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                                                  dex2oat_isa_features, NULL) > 0;
22890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
22990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    char dex2oat_isa_variant_key[kPropertyKeyMax];
23090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", instruction_set);
23190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    char dex2oat_isa_variant[kPropertyValueMax];
23290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool have_dex2oat_isa_variant = get_property(dex2oat_isa_variant_key,
23390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                                                 dex2oat_isa_variant, NULL) > 0;
23490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
23590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    const char *dex2oat_norelocation = "-Xnorelocate";
23690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool have_dex2oat_relocation_skip_flag = false;
23790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
23890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    char dex2oat_flags[kPropertyValueMax];
23990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    int dex2oat_flags_count = get_property("dalvik.vm.dex2oat-flags",
24090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                                 dex2oat_flags, NULL) <= 0 ? 0 : split_count(dex2oat_flags);
24190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags);
24290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
243a0af34de9ef2449000343b468f4a056a91dcdbb6Nicolas Geoffray    // If we are booting without the real /data, don't spend time compiling.
24490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    char vold_decrypt[kPropertyValueMax];
24590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool have_vold_decrypt = get_property("vold.decrypt", vold_decrypt, "") > 0;
24690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool skip_compilation = (have_vold_decrypt &&
24790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                             (strcmp(vold_decrypt, "trigger_restart_min_framework") == 0 ||
24890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                             (strcmp(vold_decrypt, "1") == 0)));
24990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
25090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool generate_debug_info = property_get_bool("debug.generate-debug-info", false);
25190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
25290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    char app_image_format[kPropertyValueMax];
25390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    char image_format_arg[strlen("--image-format=") + kPropertyValueMax];
25490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool have_app_image_format =
25590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            image_fd >= 0 && get_property("dalvik.vm.appimageformat", app_image_format, NULL) > 0;
25690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (have_app_image_format) {
25790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        sprintf(image_format_arg, "--image-format=%s", app_image_format);
25890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
25990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
26090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    char dex2oat_large_app_threshold[kPropertyValueMax];
26190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool have_dex2oat_large_app_threshold =
26290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            get_property("dalvik.vm.dex2oat-very-large", dex2oat_large_app_threshold, NULL) > 0;
26390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    char dex2oat_large_app_threshold_arg[strlen("--very-large-app-threshold=") + kPropertyValueMax];
26490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (have_dex2oat_large_app_threshold) {
26590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        sprintf(dex2oat_large_app_threshold_arg,
26690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                "--very-large-app-threshold=%s",
26790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                dex2oat_large_app_threshold);
26890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
26990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
27090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    static const char* DEX2OAT_BIN = "/system/bin/dex2oat";
27190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
27290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    static const char* RUNTIME_ARG = "--runtime-arg";
27390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
27490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    static const int MAX_INT_LEN = 12;      // '-'+10dig+'\0' -OR- 0x+8dig
27590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
27636cebe7778a89fa1302a8828ade93db2d014c522George Burgess IV    // clang FORTIFY doesn't let us use strlen in constant array bounds, so we
27736cebe7778a89fa1302a8828ade93db2d014c522George Burgess IV    // use arraysize instead.
27836cebe7778a89fa1302a8828ade93db2d014c522George Burgess IV    char zip_fd_arg[arraysize("--zip-fd=") + MAX_INT_LEN];
27936cebe7778a89fa1302a8828ade93db2d014c522George Burgess IV    char zip_location_arg[arraysize("--zip-location=") + PKG_PATH_MAX];
28036cebe7778a89fa1302a8828ade93db2d014c522George Burgess IV    char input_vdex_fd_arg[arraysize("--input-vdex-fd=") + MAX_INT_LEN];
28136cebe7778a89fa1302a8828ade93db2d014c522George Burgess IV    char output_vdex_fd_arg[arraysize("--output-vdex-fd=") + MAX_INT_LEN];
28236cebe7778a89fa1302a8828ade93db2d014c522George Burgess IV    char oat_fd_arg[arraysize("--oat-fd=") + MAX_INT_LEN];
28336cebe7778a89fa1302a8828ade93db2d014c522George Burgess IV    char oat_location_arg[arraysize("--oat-location=") + PKG_PATH_MAX];
28436cebe7778a89fa1302a8828ade93db2d014c522George Burgess IV    char instruction_set_arg[arraysize("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
28536cebe7778a89fa1302a8828ade93db2d014c522George Burgess IV    char instruction_set_variant_arg[arraysize("--instruction-set-variant=") + kPropertyValueMax];
28636cebe7778a89fa1302a8828ade93db2d014c522George Burgess IV    char instruction_set_features_arg[arraysize("--instruction-set-features=") + kPropertyValueMax];
28736cebe7778a89fa1302a8828ade93db2d014c522George Burgess IV    char dex2oat_Xms_arg[arraysize("-Xms") + kPropertyValueMax];
28836cebe7778a89fa1302a8828ade93db2d014c522George Burgess IV    char dex2oat_Xmx_arg[arraysize("-Xmx") + kPropertyValueMax];
28936cebe7778a89fa1302a8828ade93db2d014c522George Burgess IV    char dex2oat_compiler_filter_arg[arraysize("--compiler-filter=") + kPropertyValueMax];
29090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool have_dex2oat_swap_fd = false;
29136cebe7778a89fa1302a8828ade93db2d014c522George Burgess IV    char dex2oat_swap_fd[arraysize("--swap-fd=") + MAX_INT_LEN];
29290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool have_dex2oat_image_fd = false;
29336cebe7778a89fa1302a8828ade93db2d014c522George Burgess IV    char dex2oat_image_fd[arraysize("--app-image-fd=") + MAX_INT_LEN];
29490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
29590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
29610b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao    sprintf(zip_location_arg, "--zip-location=%s", relative_input_file_name);
29790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    sprintf(input_vdex_fd_arg, "--input-vdex-fd=%d", input_vdex_fd);
29890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    sprintf(output_vdex_fd_arg, "--output-vdex-fd=%d", output_vdex_fd);
29990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd);
30090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    sprintf(oat_location_arg, "--oat-location=%s", output_file_name);
30190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set);
30290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    sprintf(instruction_set_variant_arg, "--instruction-set-variant=%s", dex2oat_isa_variant);
30390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    sprintf(instruction_set_features_arg, "--instruction-set-features=%s", dex2oat_isa_features);
30490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (swap_fd >= 0) {
30590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        have_dex2oat_swap_fd = true;
30690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        sprintf(dex2oat_swap_fd, "--swap-fd=%d", swap_fd);
30790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
30890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (image_fd >= 0) {
30990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        have_dex2oat_image_fd = true;
31090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        sprintf(dex2oat_image_fd, "--app-image-fd=%d", image_fd);
31190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
31290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
31390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (have_dex2oat_Xms_flag) {
31490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        sprintf(dex2oat_Xms_arg, "-Xms%s", dex2oat_Xms_flag);
31590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
31690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (have_dex2oat_Xmx_flag) {
31790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        sprintf(dex2oat_Xmx_arg, "-Xmx%s", dex2oat_Xmx_flag);
31890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
31990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
32090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // Compute compiler filter.
32190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
322a0af34de9ef2449000343b468f4a056a91dcdbb6Nicolas Geoffray    bool have_dex2oat_compiler_filter_flag = false;
32390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (skip_compilation) {
32463d8e566f7396884de830a0af358f0ad2c11f302Nicolas Geoffray        strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=extract");
32590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        have_dex2oat_compiler_filter_flag = true;
32690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        have_dex2oat_relocation_skip_flag = true;
327a0af34de9ef2449000343b468f4a056a91dcdbb6Nicolas Geoffray    } else if (compiler_filter != nullptr) {
328a0af34de9ef2449000343b468f4a056a91dcdbb6Nicolas Geoffray        if (strlen(compiler_filter) + strlen("--compiler-filter=") <
32990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                    arraysize(dex2oat_compiler_filter_arg)) {
330a0af34de9ef2449000343b468f4a056a91dcdbb6Nicolas Geoffray            sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", compiler_filter);
331a0af34de9ef2449000343b468f4a056a91dcdbb6Nicolas Geoffray            have_dex2oat_compiler_filter_flag = true;
332a0af34de9ef2449000343b468f4a056a91dcdbb6Nicolas Geoffray        } else {
333a0af34de9ef2449000343b468f4a056a91dcdbb6Nicolas Geoffray            ALOGW("Compiler filter name '%s' is too large (max characters is %zu)",
334a0af34de9ef2449000343b468f4a056a91dcdbb6Nicolas Geoffray                  compiler_filter,
335a0af34de9ef2449000343b468f4a056a91dcdbb6Nicolas Geoffray                  kPropertyValueMax);
336a0af34de9ef2449000343b468f4a056a91dcdbb6Nicolas Geoffray        }
337a0af34de9ef2449000343b468f4a056a91dcdbb6Nicolas Geoffray    }
338a0af34de9ef2449000343b468f4a056a91dcdbb6Nicolas Geoffray
339a0af34de9ef2449000343b468f4a056a91dcdbb6Nicolas Geoffray    if (!have_dex2oat_compiler_filter_flag) {
34090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        char dex2oat_compiler_filter_flag[kPropertyValueMax];
34190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        have_dex2oat_compiler_filter_flag = get_property("dalvik.vm.dex2oat-filter",
34290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                                                         dex2oat_compiler_filter_flag, NULL) > 0;
34390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (have_dex2oat_compiler_filter_flag) {
34490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            sprintf(dex2oat_compiler_filter_arg,
34590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                    "--compiler-filter=%s",
34690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                    dex2oat_compiler_filter_flag);
34790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
34890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
34990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
35090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // Check whether all apps should be compiled debuggable.
35190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (!debuggable) {
35290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        char prop_buf[kPropertyValueMax];
35390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        debuggable =
35490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                (get_property("dalvik.vm.always_debuggable", prop_buf, "0") > 0) &&
35590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                (prop_buf[0] == '1');
35690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
35790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    char profile_arg[strlen("--profile-file-fd=") + MAX_INT_LEN];
35890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (profile_fd != -1) {
35990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        sprintf(profile_arg, "--profile-file-fd=%d", profile_fd);
36090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
36190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
36210b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao    // Get the directory of the apk to pass as a base classpath directory.
36310b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao    char base_dir[arraysize("--classpath-dir=") + PKG_PATH_MAX];
36410b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao    std::string apk_dir(input_file_name);
36510b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao    unsigned long dir_index = apk_dir.rfind('/');
36610b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao    bool has_base_dir = dir_index != std::string::npos;
36710b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao    if (has_base_dir) {
36810b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao        apk_dir = apk_dir.substr(0, dir_index);
36910b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao        sprintf(base_dir, "--classpath-dir=%s", apk_dir.c_str());
37010b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao    }
37110b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao
37290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
37310b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao    ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, relative_input_file_name, output_file_name);
37490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
37590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    const char* argv[9  // program name, mandatory arguments and the final NULL
37690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                     + (have_dex2oat_isa_variant ? 1 : 0)
37790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                     + (have_dex2oat_isa_features ? 1 : 0)
37890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                     + (have_dex2oat_Xms_flag ? 2 : 0)
37990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                     + (have_dex2oat_Xmx_flag ? 2 : 0)
38090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                     + (have_dex2oat_compiler_filter_flag ? 1 : 0)
38190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                     + (have_dex2oat_threads_flag ? 1 : 0)
38290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                     + (have_dex2oat_swap_fd ? 1 : 0)
38390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                     + (have_dex2oat_image_fd ? 1 : 0)
38490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                     + (have_dex2oat_relocation_skip_flag ? 2 : 0)
38590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                     + (generate_debug_info ? 1 : 0)
38690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                     + (debuggable ? 1 : 0)
38790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                     + (have_app_image_format ? 1 : 0)
38890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                     + dex2oat_flags_count
38990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                     + (profile_fd == -1 ? 0 : 1)
39090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                     + (shared_libraries != nullptr ? 4 : 0)
39110b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao                     + (has_base_dir ? 1 : 0)
39290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                     + (have_dex2oat_large_app_threshold ? 1 : 0)];
39390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    int i = 0;
39490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    argv[i++] = DEX2OAT_BIN;
39590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    argv[i++] = zip_fd_arg;
39690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    argv[i++] = zip_location_arg;
39790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    argv[i++] = input_vdex_fd_arg;
39890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    argv[i++] = output_vdex_fd_arg;
39990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    argv[i++] = oat_fd_arg;
40090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    argv[i++] = oat_location_arg;
40190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    argv[i++] = instruction_set_arg;
40290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (have_dex2oat_isa_variant) {
40390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = instruction_set_variant_arg;
40490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
40590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (have_dex2oat_isa_features) {
40690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = instruction_set_features_arg;
40790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
40890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (have_dex2oat_Xms_flag) {
40990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = RUNTIME_ARG;
41090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = dex2oat_Xms_arg;
41190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
41290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (have_dex2oat_Xmx_flag) {
41390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = RUNTIME_ARG;
41490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = dex2oat_Xmx_arg;
41590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
41690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (have_dex2oat_compiler_filter_flag) {
41790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = dex2oat_compiler_filter_arg;
41890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
41990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (have_dex2oat_threads_flag) {
42090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = dex2oat_threads_arg;
42190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
42290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (have_dex2oat_swap_fd) {
42390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = dex2oat_swap_fd;
42490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
42590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (have_dex2oat_image_fd) {
42690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = dex2oat_image_fd;
42790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
42890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (generate_debug_info) {
42990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = "--generate-debug-info";
43090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
43190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (debuggable) {
43290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = "--debuggable";
43390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
43490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (have_app_image_format) {
43590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = image_format_arg;
43690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
43790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (have_dex2oat_large_app_threshold) {
43890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = dex2oat_large_app_threshold_arg;
43990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
44090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (dex2oat_flags_count) {
44190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        i += split(dex2oat_flags, argv + i);
44290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
44390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (have_dex2oat_relocation_skip_flag) {
44490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = RUNTIME_ARG;
44590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = dex2oat_norelocation;
44690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
44790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (profile_fd != -1) {
44890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = profile_arg;
44990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
45090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (shared_libraries != nullptr) {
45190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = RUNTIME_ARG;
45290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = "-classpath";
45390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = RUNTIME_ARG;
45490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = shared_libraries;
45590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
45610b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao    if (has_base_dir) {
45710b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao        argv[i++] = base_dir;
45810b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao    }
45990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // Do not add after dex2oat_flags, they should override others for debugging.
46090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    argv[i] = NULL;
46190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
46290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    execv(DEX2OAT_BIN, (char * const *)argv);
46390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    ALOGE("execv(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno));
46490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
46590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
46690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey/*
46790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey * Whether dexopt should use a swap file when compiling an APK.
46890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey *
46990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey * If kAlwaysProvideSwapFile, do this on all devices (dex2oat will make a more informed decision
47090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey * itself, anyways).
47190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey *
47290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey * Otherwise, read "dalvik.vm.dex2oat-swap". If the property exists, return whether it is "true".
47390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey *
47490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey * Otherwise, return true if this is a low-mem device.
47590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey *
47690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey * Otherwise, return default value.
47790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey */
47890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic bool kAlwaysProvideSwapFile = false;
47990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic bool kDefaultProvideSwapFile = true;
48090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
48190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic bool ShouldUseSwapFileForDexopt() {
48290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (kAlwaysProvideSwapFile) {
48390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return true;
48490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
48590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
48690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // Check the "override" property. If it exists, return value == "true".
48790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    char dex2oat_prop_buf[kPropertyValueMax];
48890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (get_property("dalvik.vm.dex2oat-swap", dex2oat_prop_buf, "") > 0) {
48990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (strcmp(dex2oat_prop_buf, "true") == 0) {
49090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            return true;
49190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        } else {
49290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            return false;
49390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
49490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
49590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
49690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // Shortcut for default value. This is an implementation optimization for the process sketched
49790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // above. If the default value is true, we can avoid to check whether this is a low-mem device,
49890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // as low-mem is never returning false. The compiler will optimize this away if it can.
49990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (kDefaultProvideSwapFile) {
50090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return true;
50190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
50290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
50390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool is_low_mem = property_get_bool("ro.config.low_ram", false);
50490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (is_low_mem) {
50590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return true;
50690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
50790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
50890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // Default value must be false here.
50990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    return kDefaultProvideSwapFile;
51090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
51190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
51276cc027ca6ebfd2f870c1cbb8f1d1fd19e0ac8e9Richard Uhlerstatic void SetDex2OatScheduling(bool set_to_bg) {
51390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (set_to_bg) {
51490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (set_sched_policy(0, SP_BACKGROUND) < 0) {
51590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            ALOGE("set_sched_policy failed: %s\n", strerror(errno));
51690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            exit(70);
51790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
51890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
51990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            ALOGE("setpriority failed: %s\n", strerror(errno));
52090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            exit(71);
52190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
52290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
52390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
52490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
525114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravlestatic bool create_profile(int uid, const std::string& profile) {
526114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    unique_fd fd(TEMP_FAILURE_RETRY(open(profile.c_str(), O_CREAT | O_NOFOLLOW, 0600)));
527114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    if (fd.get() < 0) {
528114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        if (errno == EEXIST) {
529114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            return true;
530114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        } else {
531114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            PLOG(ERROR) << "Failed to create profile " << profile;
532114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            return false;
53390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
53490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
535114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    // Profiles should belong to the app; make sure of that by giving ownership to
536114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    // the app uid. If we cannot do that, there's no point in returning the fd
537114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    // since dex2oat/profman will fail with SElinux denials.
538114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    if (fchown(fd.get(), uid, uid) < 0) {
539114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        PLOG(ERROR) << "Could not chwon profile " << profile;
540114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        return false;
541114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    }
542114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    return true;
54390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
54490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
545114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravlestatic unique_fd open_profile(int uid, const std::string& profile, bool read_write) {
546114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    // Check if we need to open the profile for a read-write operation. If so, we
547114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    // might need to create the profile since the file might not be there. Reference
548114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    // profiles are created on the fly so they might not exist beforehand.
549114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    if (read_write) {
550114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        if (!create_profile(uid, profile)) {
551114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            return invalid_unique_fd();
552114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        }
55390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
554114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    int flags = read_write ? O_RDWR : O_RDONLY;
555114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    // Do not follow symlinks when opening a profile:
556114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    //   - primary profiles should not contain symlinks in their paths
557114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    //   - secondary dex paths should have been already resolved and validated
558114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    flags |= O_NOFOLLOW;
55990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
560114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    unique_fd fd(TEMP_FAILURE_RETRY(open(profile.c_str(), flags)));
561114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    if (fd.get() < 0) {
56290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (errno != ENOENT) {
563114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            // Profiles might be missing for various reasons. For example, in a
564114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            // multi-user environment, the profile directory for one user can be created
565114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            // after we start a merge. In this case the current profile for that user
566114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            // will not be found.
567114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            // Also, the secondary dex profiles might be deleted by the app at any time,
568114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            // so we can't we need to prepare if they are missing.
569114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            PLOG(ERROR) << "Failed to open profile " << profile;
57090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
571114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        return invalid_unique_fd();
57290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
573114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle
574114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    return fd;
57590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
57690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
577114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravlestatic unique_fd open_current_profile(uid_t uid, userid_t user, const std::string& location,
578114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        bool is_secondary_dex) {
579114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    std::string profile = create_current_profile_path(user, location, is_secondary_dex);
580114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    return open_profile(uid, profile, /*read_write*/false);
58190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
58290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
583114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravlestatic unique_fd open_reference_profile(uid_t uid, const std::string& location, bool read_write,
584114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        bool is_secondary_dex) {
585114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    std::string profile = create_reference_profile_path(location, is_secondary_dex);
586114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    return open_profile(uid, profile, read_write);
58790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
58890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
589114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravlestatic void open_profile_files(uid_t uid, const std::string& location, bool is_secondary_dex,
5901a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle            /*out*/ std::vector<unique_fd>* profiles_fd, /*out*/ unique_fd* reference_profile_fd) {
59190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // Open the reference profile in read-write mode as profman might need to save the merge.
592114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    *reference_profile_fd = open_reference_profile(uid, location, /*read_write*/ true,
593114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            is_secondary_dex);
594114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle
595114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    // For secondary dex files, we don't really need the user but we use it for sanity checks.
596114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    // Note: the user owning the dex file should be the current user.
597114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    std::vector<userid_t> users;
598114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    if (is_secondary_dex){
599114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        users.push_back(multiuser_get_user_id(uid));
600114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    } else {
601114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        users = get_known_users(/*volume_uuid*/ nullptr);
60290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
60390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    for (auto user : users) {
604114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        unique_fd profile_fd = open_current_profile(uid, user, location, is_secondary_dex);
60590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        // Add to the lists only if both fds are valid.
6061a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle        if (profile_fd.get() >= 0) {
6071a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle            profiles_fd->push_back(std::move(profile_fd));
60890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
60990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
61090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
61190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
61290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic void drop_capabilities(uid_t uid) {
61390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (setgid(uid) != 0) {
61490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        ALOGE("setgid(%d) failed in installd during dexopt\n", uid);
61590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        exit(64);
61690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
61790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (setuid(uid) != 0) {
61890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        ALOGE("setuid(%d) failed in installd during dexopt\n", uid);
61990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        exit(65);
62090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
62190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // drop capabilities
62290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    struct __user_cap_header_struct capheader;
62390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    struct __user_cap_data_struct capdata[2];
62490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    memset(&capheader, 0, sizeof(capheader));
62590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    memset(&capdata, 0, sizeof(capdata));
62690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    capheader.version = _LINUX_CAPABILITY_VERSION_3;
62790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (capset(&capheader, &capdata[0]) < 0) {
62890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        ALOGE("capset failed: %s\n", strerror(errno));
62990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        exit(66);
63090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
63190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
63290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
63390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic constexpr int PROFMAN_BIN_RETURN_CODE_COMPILE = 0;
63490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic constexpr int PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION = 1;
63590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic constexpr int PROFMAN_BIN_RETURN_CODE_BAD_PROFILES = 2;
63690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3;
63790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4;
63890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
6391a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravlestatic void run_profman_merge(const std::vector<unique_fd>& profiles_fd,
6401a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle        const unique_fd& reference_profile_fd) {
64190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    static const size_t MAX_INT_LEN = 32;
64290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    static const char* PROFMAN_BIN = "/system/bin/profman";
64390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
64490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    std::vector<std::string> profile_args(profiles_fd.size());
64590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    char profile_buf[strlen("--profile-file-fd=") + MAX_INT_LEN];
64690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    for (size_t k = 0; k < profiles_fd.size(); k++) {
6471a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle        sprintf(profile_buf, "--profile-file-fd=%d", profiles_fd[k].get());
64890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        profile_args[k].assign(profile_buf);
64990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
65090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    char reference_profile_arg[strlen("--reference-profile-file-fd=") + MAX_INT_LEN];
6511a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle    sprintf(reference_profile_arg, "--reference-profile-file-fd=%d", reference_profile_fd.get());
65290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
65390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // program name, reference profile fd, the final NULL and the profile fds
65490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    const char* argv[3 + profiles_fd.size()];
65590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    int i = 0;
65690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    argv[i++] = PROFMAN_BIN;
65790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    argv[i++] = reference_profile_arg;
65890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    for (size_t k = 0; k < profile_args.size(); k++) {
65990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = profile_args[k].c_str();
66090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
66190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // Do not add after dex2oat_flags, they should override others for debugging.
66290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    argv[i] = NULL;
66390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
66490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    execv(PROFMAN_BIN, (char * const *)argv);
66590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    ALOGE("execv(%s) failed: %s\n", PROFMAN_BIN, strerror(errno));
66690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    exit(68);   /* only get here on exec failure */
66790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
66890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
66990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey// Decides if profile guided compilation is needed or not based on existing profiles.
670114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle// The location is the package name for primary apks or the dex path for secondary dex files.
671114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle// Returns true if there is enough information in the current profiles that makes it
672114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle// worth to recompile the given location.
67390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey// If the return value is true all the current profiles would have been merged into
67490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey// the reference profiles accessible with open_reference_profile().
675114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravlestatic bool analyze_profiles(uid_t uid, const std::string& location, bool is_secondary_dex) {
6761a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle    std::vector<unique_fd> profiles_fd;
6771a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle    unique_fd reference_profile_fd;
678114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    open_profile_files(uid, location, is_secondary_dex, &profiles_fd, &reference_profile_fd);
6791a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle    if (profiles_fd.empty() || (reference_profile_fd.get() < 0)) {
68090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        // Skip profile guided compilation because no profiles were found.
68190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        // Or if the reference profile info couldn't be opened.
68290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return false;
68390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
68490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
68590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    pid_t pid = fork();
68690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (pid == 0) {
68790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        /* child -- drop privileges before continuing */
68890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        drop_capabilities(uid);
68990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        run_profman_merge(profiles_fd, reference_profile_fd);
69090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        exit(68);   /* only get here on exec failure */
69190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
69290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    /* parent */
69390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    int return_code = wait_child(pid);
69490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool need_to_compile = false;
69590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool should_clear_current_profiles = false;
69690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool should_clear_reference_profile = false;
69790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (!WIFEXITED(return_code)) {
698114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        LOG(WARNING) << "profman failed for location " << location << ": " << return_code;
69990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    } else {
70090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return_code = WEXITSTATUS(return_code);
70190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        switch (return_code) {
70290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            case PROFMAN_BIN_RETURN_CODE_COMPILE:
70390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                need_to_compile = true;
70490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                should_clear_current_profiles = true;
70590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                should_clear_reference_profile = false;
70690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                break;
70790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            case PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION:
70890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                need_to_compile = false;
70990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                should_clear_current_profiles = false;
71090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                should_clear_reference_profile = false;
71190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                break;
71290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            case PROFMAN_BIN_RETURN_CODE_BAD_PROFILES:
713114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle                LOG(WARNING) << "Bad profiles for location " << location;
71490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                need_to_compile = false;
71590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                should_clear_current_profiles = true;
71690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                should_clear_reference_profile = true;
71790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                break;
71890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            case PROFMAN_BIN_RETURN_CODE_ERROR_IO:  // fall-through
71990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            case PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING:
72090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                // Temporary IO problem (e.g. locking). Ignore but log a warning.
721114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle                LOG(WARNING) << "IO error while reading profiles for location " << location;
72290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                need_to_compile = false;
72390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                should_clear_current_profiles = false;
72490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                should_clear_reference_profile = false;
72590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                break;
72690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey           default:
72790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                // Unknown return code or error. Unlink profiles.
728114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle                LOG(WARNING) << "Unknown error code while processing profiles for location "
729114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle                        << location << ": " << return_code;
73090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                need_to_compile = false;
73190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                should_clear_current_profiles = true;
73290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                should_clear_reference_profile = true;
73390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                break;
73490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
73590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
7361a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle
73790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (should_clear_current_profiles) {
738114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        if (is_secondary_dex) {
739114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            // For secondary dex files, the owning user is the current user.
740114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            clear_current_profile(location, multiuser_get_user_id(uid), is_secondary_dex);
741114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        } else  {
742114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            clear_primary_current_profiles(location);
743114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        }
74490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
74590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (should_clear_reference_profile) {
746114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        clear_reference_profile(location, is_secondary_dex);
74790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
74890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    return need_to_compile;
74990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
75090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
751114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle// Decides if profile guided compilation is needed or not based on existing profiles.
752114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle// The analysis is done for the primary apks of the given package.
753114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle// Returns true if there is enough information in the current profiles that makes it
754114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle// worth to recompile the package.
755114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle// If the return value is true all the current profiles would have been merged into
756114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle// the reference profiles accessible with open_reference_profile().
757114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravlebool analyze_primary_profiles(uid_t uid, const std::string& pkgname) {
758114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    return analyze_profiles(uid, pkgname, /*is_secondary_dex*/false);
759114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle}
760114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle
7611a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravlestatic void run_profman_dump(const std::vector<unique_fd>& profile_fds,
7621a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle                             const unique_fd& reference_profile_fd,
76390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                             const std::vector<std::string>& dex_locations,
7641a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle                             const std::vector<unique_fd>& apk_fds,
7651a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle                             const unique_fd& output_fd) {
76690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    std::vector<std::string> profman_args;
76790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    static const char* PROFMAN_BIN = "/system/bin/profman";
76890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    profman_args.push_back(PROFMAN_BIN);
76990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    profman_args.push_back("--dump-only");
7701a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle    profman_args.push_back(StringPrintf("--dump-output-to-fd=%d", output_fd.get()));
77190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (reference_profile_fd != -1) {
77290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        profman_args.push_back(StringPrintf("--reference-profile-file-fd=%d",
7731a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle                                            reference_profile_fd.get()));
77490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
7751a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle    for (size_t i = 0; i < profile_fds.size(); i++) {
7761a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle        profman_args.push_back(StringPrintf("--profile-file-fd=%d", profile_fds[i].get()));
77790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
77890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    for (const std::string& dex_location : dex_locations) {
77990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        profman_args.push_back(StringPrintf("--dex-location=%s", dex_location.c_str()));
78090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
7811a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle    for (size_t i = 0; i < apk_fds.size(); i++) {
7821a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle        profman_args.push_back(StringPrintf("--apk-fd=%d", apk_fds[i].get()));
78390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
78490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    const char **argv = new const char*[profman_args.size() + 1];
78590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    size_t i = 0;
78690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    for (const std::string& profman_arg : profman_args) {
78790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        argv[i++] = profman_arg.c_str();
78890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
78990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    argv[i] = NULL;
79090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
79190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    execv(PROFMAN_BIN, (char * const *)argv);
79290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    ALOGE("execv(%s) failed: %s\n", PROFMAN_BIN, strerror(errno));
79390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    exit(68);   /* only get here on exec failure */
79490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
79590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
79676268c56febde9a77183387fbd4baabe6694e6b5Calin Juravlebool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths) {
7971a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle    std::vector<unique_fd> profile_fds;
7981a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle    unique_fd reference_profile_fd;
79976268c56febde9a77183387fbd4baabe6694e6b5Calin Juravle    std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname.c_str());
80090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
801114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    open_profile_files(uid, pkgname, /*is_secondary_dex*/false,
802114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            &profile_fds, &reference_profile_fd);
80390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
8041a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle    const bool has_reference_profile = (reference_profile_fd.get() != -1);
80590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    const bool has_profiles = !profile_fds.empty();
80690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
80790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (!has_reference_profile && !has_profiles) {
80876268c56febde9a77183387fbd4baabe6694e6b5Calin Juravle        LOG(ERROR)  << "profman dump: no profiles to dump for " << pkgname;
80990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return false;
81090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
81190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
812114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    unique_fd output_fd(open(out_file_name.c_str(),
813114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0644));
81490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (fchmod(output_fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
81590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        ALOGE("installd cannot chmod '%s' dump_profile\n", out_file_name.c_str());
81690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return false;
81790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
81890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    std::vector<std::string> code_full_paths = base::Split(code_paths, ";");
81990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    std::vector<std::string> dex_locations;
8201a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle    std::vector<unique_fd> apk_fds;
82190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    for (const std::string& code_full_path : code_full_paths) {
82290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        const char* full_path = code_full_path.c_str();
8231a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle        unique_fd apk_fd(open(full_path, O_RDONLY | O_NOFOLLOW));
82490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (apk_fd == -1) {
82590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            ALOGE("installd cannot open '%s'\n", full_path);
82690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            return false;
82790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
82890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        dex_locations.push_back(get_location_from_path(full_path));
8291a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle        apk_fds.push_back(std::move(apk_fd));
83090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
83190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
83290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    pid_t pid = fork();
83390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (pid == 0) {
83490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        /* child -- drop privileges before continuing */
83590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        drop_capabilities(uid);
83690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        run_profman_dump(profile_fds, reference_profile_fd, dex_locations,
83790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                         apk_fds, output_fd);
83890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        exit(68);   /* only get here on exec failure */
83990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
84090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    /* parent */
84190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    int return_code = wait_child(pid);
84290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (!WIFEXITED(return_code)) {
84390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        LOG(WARNING) << "profman failed for package " << pkgname << ": "
84490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                << return_code;
84590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return false;
84690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
84790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    return true;
84890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
84990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
85090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic std::string replace_file_extension(const std::string& oat_path, const std::string& new_ext) {
85190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  // A standard dalvik-cache entry. Replace ".dex" with `new_ext`.
85290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  if (EndsWith(oat_path, ".dex")) {
85390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    std::string new_path = oat_path;
85490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    new_path.replace(new_path.length() - strlen(".dex"), strlen(".dex"), new_ext);
85590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    CHECK(EndsWith(new_path, new_ext.c_str()));
85690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    return new_path;
85790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  }
85890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
85990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  // An odex entry. Not that this may not be an extension, e.g., in the OTA
86090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  // case (where the base name will have an extension for the B artifact).
86190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  size_t odex_pos = oat_path.rfind(".odex");
86290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  if (odex_pos != std::string::npos) {
86390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    std::string new_path = oat_path;
86490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    new_path.replace(odex_pos, strlen(".odex"), new_ext);
86590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    CHECK_NE(new_path.find(new_ext), std::string::npos);
86690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    return new_path;
86790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  }
86890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
86990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  // Don't know how to handle this.
87090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  return "";
87190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
87290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
87390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey// Translate the given oat path to an art (app image) path. An empty string
87490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey// denotes an error.
87590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic std::string create_image_filename(const std::string& oat_path) {
87690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    return replace_file_extension(oat_path, ".art");
87790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
87890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
87990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey// Translate the given oat path to a vdex path. An empty string denotes an error.
88090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic std::string create_vdex_filename(const std::string& oat_path) {
88190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    return replace_file_extension(oat_path, ".vdex");
88290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
88390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
88490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic bool add_extension_to_file_name(char* file_name, const char* extension) {
88590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (strlen(file_name) + strlen(extension) + 1 > PKG_PATH_MAX) {
88690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return false;
88790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
88890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    strcat(file_name, extension);
88990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    return true;
89090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
89190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
89290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic int open_output_file(const char* file_name, bool recreate, int permissions) {
89390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    int flags = O_RDWR | O_CREAT;
89490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (recreate) {
89590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (unlink(file_name) < 0) {
89690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            if (errno != ENOENT) {
89790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                PLOG(ERROR) << "open_output_file: Couldn't unlink " << file_name;
89890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            }
89990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
90090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        flags |= O_EXCL;
90190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
90290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    return open(file_name, flags, permissions);
90390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
90490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
9052289c0ac89acce109b3e93c434d86b20c5ecc1adCalin Juravlestatic bool set_permissions_and_ownership(
9062289c0ac89acce109b3e93c434d86b20c5ecc1adCalin Juravle        int fd, bool is_public, int uid, const char* path, bool is_secondary_dex) {
9072289c0ac89acce109b3e93c434d86b20c5ecc1adCalin Juravle    // Primary apks are owned by the system. Secondary dex files are owned by the app.
9082289c0ac89acce109b3e93c434d86b20c5ecc1adCalin Juravle    int owning_uid = is_secondary_dex ? uid : AID_SYSTEM;
90990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (fchmod(fd,
91090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey               S_IRUSR|S_IWUSR|S_IRGRP |
91190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey               (is_public ? S_IROTH : 0)) < 0) {
91290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        ALOGE("installd cannot chmod '%s' during dexopt\n", path);
91390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return false;
9142289c0ac89acce109b3e93c434d86b20c5ecc1adCalin Juravle    } else if (fchown(fd, owning_uid, uid) < 0) {
91590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        ALOGE("installd cannot chown '%s' during dexopt\n", path);
91690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return false;
91790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
91890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    return true;
91990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
92090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
92190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic bool IsOutputDalvikCache(const char* oat_dir) {
92290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  // InstallerConnection.java (which invokes installd) transforms Java null arguments
92390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  // into '!'. Play it safe by handling it both.
92490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  // TODO: ensure we never get null.
92590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  // TODO: pass a flag instead of inferring if the output is dalvik cache.
92690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey  return oat_dir == nullptr || oat_dir[0] == '!';
92790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
92890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
92990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic bool create_oat_out_path(const char* apk_path, const char* instruction_set,
93080a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle            const char* oat_dir, bool is_secondary_dex, /*out*/ char* out_oat_path) {
93190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // Early best-effort check whether we can fit the the path into our buffers.
93290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // Note: the cache path will require an additional 5 bytes for ".swap", but we'll try to run
93390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // without a swap file, if necessary. Reference profiles file also add an extra ".prof"
93490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // extension to the cache path (5 bytes).
93590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) {
93690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        ALOGE("apk_path too long '%s'\n", apk_path);
93790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return false;
93890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
93990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
94090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (!IsOutputDalvikCache(oat_dir)) {
94180a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        // Oat dirs for secondary dex files are already validated.
94280a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        if (!is_secondary_dex && validate_apk_path(oat_dir)) {
94390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            ALOGE("cannot validate apk path with oat_dir '%s'\n", oat_dir);
94490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            return false;
94590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
94690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (!calculate_oat_file_path(out_oat_path, oat_dir, apk_path, instruction_set)) {
94790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            return false;
94890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
94990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    } else {
95090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (!create_cache_path(out_oat_path, apk_path, instruction_set)) {
95190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            return false;
95290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
95390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
95490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    return true;
95590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
95690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
95790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey// Helper for fd management. This is similar to a unique_fd in that it closes the file descriptor
95890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey// on destruction. It will also run the given cleanup (unless told not to) after closing.
95990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//
96090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey// Usage example:
96190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//
9627a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle//   Dex2oatFileWrapper file(open(...),
96390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//                                                   [name]() {
96490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//                                                       unlink(name.c_str());
96590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//                                                   });
96690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//   // Note: care needs to be taken about name, as it needs to have a lifetime longer than the
96790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//            wrapper if captured as a reference.
96890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//
96990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//   if (file.get() == -1) {
97090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//       // Error opening...
97190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//   }
97290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//
97390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//   ...
97490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//   if (error) {
97590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//       // At this point, when the Dex2oatFileWrapper is destructed, the cleanup function will run
97690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//       // and delete the file (after the fd is closed).
97790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//       return -1;
97890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//   }
97990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//
98090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//   (Success case)
98190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//   file.SetCleanup(false);
98290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//   // At this point, when the Dex2oatFileWrapper is destructed, the cleanup function will not run
98390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//   // (leaving the file around; after the fd is closed).
98490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey//
98590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeyclass Dex2oatFileWrapper {
98690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey public:
9877a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    Dex2oatFileWrapper() : value_(-1), cleanup_(), do_cleanup_(true), auto_close_(true) {
98890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
98990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
9907a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    Dex2oatFileWrapper(int value, std::function<void ()> cleanup)
9917a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle            : value_(value), cleanup_(cleanup), do_cleanup_(true), auto_close_(true) {}
9927a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle
9937a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    Dex2oatFileWrapper(Dex2oatFileWrapper&& other) {
9947a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        value_ = other.value_;
9957a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        cleanup_ = other.cleanup_;
9967a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        do_cleanup_ = other.do_cleanup_;
9977a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        auto_close_ = other.auto_close_;
9987a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        other.release();
9997a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    }
10007a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle
10017a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    Dex2oatFileWrapper& operator=(Dex2oatFileWrapper&& other) {
10027a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        value_ = other.value_;
10037a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        cleanup_ = other.cleanup_;
10047a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        do_cleanup_ = other.do_cleanup_;
10057a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        auto_close_ = other.auto_close_;
10067a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        other.release();
10077a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        return *this;
10087a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    }
100990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
101090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    ~Dex2oatFileWrapper() {
101190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        reset(-1);
101290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
101390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
101490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    int get() {
101590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return value_;
101690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
101790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
101890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    void SetCleanup(bool cleanup) {
101990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        do_cleanup_ = cleanup;
102090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
102190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
102290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    void reset(int new_value) {
10237a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        if (auto_close_ && value_ >= 0) {
102490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            close(value_);
102590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
102690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (do_cleanup_ && cleanup_ != nullptr) {
102790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            cleanup_();
102890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
102990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
103090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        value_ = new_value;
103190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
103290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
10337a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    void reset(int new_value, std::function<void ()> new_cleanup) {
10347a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        if (auto_close_ && value_ >= 0) {
103590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            close(value_);
103690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
103790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (do_cleanup_ && cleanup_ != nullptr) {
103890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            cleanup_();
103990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
104090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
104190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        value_ = new_value;
104290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        cleanup_ = new_cleanup;
104390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
104490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
10457a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    void DisableAutoClose() {
10467a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        auto_close_ = false;
10477a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    }
10487a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle
104990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey private:
10507a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    void release() {
10517a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        value_ = -1;
10527a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        do_cleanup_ = false;
10537a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        cleanup_ = nullptr;
10547a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    }
105590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    int value_;
10567a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    std::function<void ()> cleanup_;
105790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool do_cleanup_;
10587a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    bool auto_close_;
105990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey};
106090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
10617a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle// (re)Creates the app image if needed.
10627a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin JuravleDex2oatFileWrapper maybe_open_app_image(const char* out_oat_path, bool profile_guided,
10632289c0ac89acce109b3e93c434d86b20c5ecc1adCalin Juravle        bool is_public, int uid, bool is_secondary_dex) {
10647a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    // Use app images only if it is enabled (by a set image format) and we are compiling
10657a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    // profile-guided (so the app image doesn't conservatively contain all classes).
10662289c0ac89acce109b3e93c434d86b20c5ecc1adCalin Juravle    // Note that we don't create an image for secondary dex files.
10672289c0ac89acce109b3e93c434d86b20c5ecc1adCalin Juravle    if (is_secondary_dex || !profile_guided) {
10687a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        return Dex2oatFileWrapper();
106990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
107090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
10717a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    const std::string image_path = create_image_filename(out_oat_path);
10727a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    if (image_path.empty()) {
10737a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        // Happens when the out_oat_path has an unknown extension.
10747a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        return Dex2oatFileWrapper();
107590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
10767a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    char app_image_format[kPropertyValueMax];
10777a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    bool have_app_image_format =
10787a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle            get_property("dalvik.vm.appimageformat", app_image_format, NULL) > 0;
10797a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    if (!have_app_image_format) {
10807a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        return Dex2oatFileWrapper();
10817a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    }
10827a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    // Recreate is true since we do not want to modify a mapped image. If the app is
10837a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    // already running and we modify the image file, it can cause crashes (b/27493510).
10847a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    Dex2oatFileWrapper wrapper_fd(
10857a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle            open_output_file(image_path.c_str(), true /*recreate*/, 0600 /*permissions*/),
10867a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle            [image_path]() { unlink(image_path.c_str()); });
10877a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    if (wrapper_fd.get() < 0) {
10887a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        // Could not create application image file. Go on since we can compile without it.
10897a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        LOG(ERROR) << "installd could not create '" << image_path
10907a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle                << "' for image file during dexopt";
10917a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle         // If we have a valid image file path but no image fd, explicitly erase the image file.
10927a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        if (unlink(image_path.c_str()) < 0) {
10937a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle            if (errno != ENOENT) {
10947a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle                PLOG(ERROR) << "Couldn't unlink image file " << image_path;
10957a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle            }
10967a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        }
10977a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    } else if (!set_permissions_and_ownership(
10982289c0ac89acce109b3e93c434d86b20c5ecc1adCalin Juravle                wrapper_fd.get(), is_public, uid, image_path.c_str(), is_secondary_dex)) {
10997a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        ALOGE("installd cannot set owner '%s' for image during dexopt\n", image_path.c_str());
11007a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        wrapper_fd.reset(-1);
110190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
110290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
11037a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    return wrapper_fd;
11047a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle}
110590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
11067a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle// Creates the dexopt swap file if necessary and return its fd.
11077a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle// Returns -1 if there's no need for a swap or in case of errors.
11081a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravleunique_fd maybe_open_dexopt_swap_file(const char* out_oat_path) {
11097a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    if (!ShouldUseSwapFileForDexopt()) {
11101a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle        return invalid_unique_fd();
11117a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    }
11127a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    // Make sure there really is enough space.
11137a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    char swap_file_name[PKG_PATH_MAX];
11147a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    strcpy(swap_file_name, out_oat_path);
11157a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    if (!add_extension_to_file_name(swap_file_name, ".swap")) {
11161a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle        return invalid_unique_fd();
11177a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    }
11181a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle    unique_fd swap_fd(open_output_file(
11197a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle            swap_file_name, /*recreate*/true, /*permissions*/0600));
11207a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    if (swap_fd.get() < 0) {
11217a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        // Could not create swap file. Optimistically go on and hope that we can compile
11227a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        // without it.
11237a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        ALOGE("installd could not create '%s' for swap during dexopt\n", swap_file_name);
11247a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    } else {
11257a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        // Immediately unlink. We don't really want to hit flash.
11267a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        if (unlink(swap_file_name) < 0) {
11277a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle            PLOG(ERROR) << "Couldn't unlink swap file " << swap_file_name;
11287a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        }
112990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
11307a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    return swap_fd;
11317a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle}
113290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
11337a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle// Opens the reference profiles if needed.
11347a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle// Note that the reference profile might not exist so it's OK if the fd will be -1.
1135114f08107be384a3f9cc954bdec2b6b7619354aeCalin JuravleDex2oatFileWrapper maybe_open_reference_profile(const std::string& pkgname,
1136114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        const std::string& dex_path, bool profile_guided, bool is_public, int uid,
1137114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        bool is_secondary_dex) {
11387a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    // Public apps should not be compiled with profile information ever. Same goes for the special
11397a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    // package '*' used for the system server.
1140114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    if (!profile_guided || is_public || (pkgname[0] == '*')) {
11417a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        return Dex2oatFileWrapper();
114290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
1143114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle
1144114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    // Open reference profile in read only mode as dex2oat does not get write permissions.
1145114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    const std::string location = is_secondary_dex ? dex_path : pkgname;
1146114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    unique_fd ufd = open_reference_profile(uid, location, /*read_write*/false, is_secondary_dex);
1147114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    const auto& cleanup = [location, is_secondary_dex]() {
1148114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        clear_reference_profile(location.c_str(), is_secondary_dex);
1149114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    };
1150114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    return Dex2oatFileWrapper(ufd.release(), cleanup);
11517a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle}
115290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
11537a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle// Opens the vdex files and assigns the input fd to in_vdex_wrapper_fd and the output fd to
11547a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle// out_vdex_wrapper_fd. Returns true for success or false in case of errors.
11557a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravlebool open_vdex_files(const char* apk_path, const char* out_oat_path, int dexopt_needed,
1156575fc2c3c8f67be2a258cf28f915c7c902f332d1Nicolas Geoffray        const char* instruction_set, bool is_public, int uid, bool is_secondary_dex,
115776689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        bool profile_guided, Dex2oatFileWrapper* in_vdex_wrapper_fd,
11587a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        Dex2oatFileWrapper* out_vdex_wrapper_fd) {
11597a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    CHECK(in_vdex_wrapper_fd != nullptr);
11607a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    CHECK(out_vdex_wrapper_fd != nullptr);
116190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // Open the existing VDEX. We do this before creating the new output VDEX, which will
116290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // unlink the old one.
116376cc027ca6ebfd2f870c1cbb8f1d1fd19e0ac8e9Richard Uhler    char in_odex_path[PKG_PATH_MAX];
116476cc027ca6ebfd2f870c1cbb8f1d1fd19e0ac8e9Richard Uhler    int dexopt_action = abs(dexopt_needed);
116576cc027ca6ebfd2f870c1cbb8f1d1fd19e0ac8e9Richard Uhler    bool is_odex_location = dexopt_needed < 0;
116690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    std::string in_vdex_path_str;
116776689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray
116876689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray    // Infer the name of the output VDEX.
116976689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray    const std::string out_vdex_path_str = create_vdex_filename(out_oat_path);
117076689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray    if (out_vdex_path_str.empty()) {
117176689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        return false;
117276689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray    }
117376689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray
117476689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray    bool update_vdex_in_place = false;
1175575fc2c3c8f67be2a258cf28f915c7c902f332d1Nicolas Geoffray    if (dexopt_action != DEX2OAT_FROM_SCRATCH) {
117690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        // Open the possibly existing vdex. If none exist, we pass -1 to dex2oat for input-vdex-fd.
117790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        const char* path = nullptr;
117890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (is_odex_location) {
117990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            if (calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) {
118090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                path = in_odex_path;
118190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            } else {
118290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                ALOGE("installd cannot compute input vdex location for '%s'\n", apk_path);
11837a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle                return false;
118490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            }
118590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        } else {
118690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            path = out_oat_path;
118790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
118890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        in_vdex_path_str = create_vdex_filename(path);
118990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (in_vdex_path_str.empty()) {
119090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            ALOGE("installd cannot compute input vdex location for '%s'\n", path);
11917a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle            return false;
119290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
119376689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        // We can update in place when all these conditions are met:
119476689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        // 1) The vdex location to write to is the same as the vdex location to read (vdex files
119576689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        //    on /system typically cannot be updated in place).
119676689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        // 2) We dex2oat due to boot image change, because we then know the existing vdex file
119776689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        //    cannot be currently used by a running process.
119876689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        // 3) We are not doing a profile guided compilation, because dexlayout requires two
119976689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        //    different vdex files to operate.
120076689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        update_vdex_in_place =
120176689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray            (in_vdex_path_str == out_vdex_path_str) &&
120276689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray            (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE) &&
120376689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray            !profile_guided;
120476689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        if (update_vdex_in_place) {
120576689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray            // Open the file read-write to be able to update it.
120676689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray            in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDWR, 0));
120776689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray            if (in_vdex_wrapper_fd->get() == -1) {
120876689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray                // If we failed to open the file, we cannot update it in place.
120976689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray                update_vdex_in_place = false;
121076689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray            }
121176689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        } else {
121276689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray            in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
121376689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        }
121490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
1215ca12228bc2a27b1cd01b820d01b2ef17622cc730Nicolas Geoffray
121676689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray    // If we are updating the vdex in place, we do not need to recreate a vdex,
121776689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray    // and can use the same existing one.
121876689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray    if (update_vdex_in_place) {
121976689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        // We unlink the file in case the invocation of dex2oat fails, to ensure we don't
122076689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        // have bogus stale vdex files.
122176689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        out_vdex_wrapper_fd->reset(
122276689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray              in_vdex_wrapper_fd->get(),
122376689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray              [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
122476689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        // Disable auto close for the in wrapper fd (it will be done when destructing the out
122576689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        // wrapper).
122676689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        in_vdex_wrapper_fd->DisableAutoClose();
122776689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray    } else {
122876689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        out_vdex_wrapper_fd->reset(
122976689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray              open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
123076689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray              [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
123176689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        if (out_vdex_wrapper_fd->get() < 0) {
123276689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray            ALOGE("installd cannot open vdex'%s' during dexopt\n", out_vdex_path_str.c_str());
123376689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray            return false;
123476689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray        }
123590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
12367a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    if (!set_permissions_and_ownership(out_vdex_wrapper_fd->get(), is_public, uid,
12372289c0ac89acce109b3e93c434d86b20c5ecc1adCalin Juravle            out_vdex_path_str.c_str(), is_secondary_dex)) {
12387a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        ALOGE("installd cannot set owner '%s' for vdex during dexopt\n", out_vdex_path_str.c_str());
12397a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        return false;
12407a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    }
12417a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle
12427a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    // If we got here we successfully opened the vdex files.
12437a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    return true;
12447a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle}
12457a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle
12467a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle// Opens the output oat file for the given apk.
12477a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle// If successful it stores the output path into out_oat_path and returns true.
12487a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin JuravleDex2oatFileWrapper open_oat_out_file(const char* apk_path, const char* oat_dir,
124980a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        bool is_public, int uid, const char* instruction_set, bool is_secondary_dex,
125080a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        char* out_oat_path) {
125180a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    if (!create_oat_out_path(apk_path, instruction_set, oat_dir, is_secondary_dex, out_oat_path)) {
12527a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        return Dex2oatFileWrapper();
12537a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    }
12547a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    const std::string out_oat_path_str(out_oat_path);
12557a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    Dex2oatFileWrapper wrapper_fd(
12567a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle            open_output_file(out_oat_path, /*recreate*/true, /*permissions*/0644),
12577a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle            [out_oat_path_str]() { unlink(out_oat_path_str.c_str()); });
12587a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    if (wrapper_fd.get() < 0) {
125980a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        PLOG(ERROR) << "installd cannot open output during dexopt" <<  out_oat_path;
12602289c0ac89acce109b3e93c434d86b20c5ecc1adCalin Juravle    } else if (!set_permissions_and_ownership(
12612289c0ac89acce109b3e93c434d86b20c5ecc1adCalin Juravle                wrapper_fd.get(), is_public, uid, out_oat_path, is_secondary_dex)) {
12627a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        ALOGE("installd cannot set owner '%s' for output during dexopt\n", out_oat_path);
12637a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        wrapper_fd.reset(-1);
12647a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    }
12657a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    return wrapper_fd;
12667a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle}
12677a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle
12687a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle// Updates the access times of out_oat_path based on those from apk_path.
12697a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravlevoid update_out_oat_access_times(const char* apk_path, const char* out_oat_path) {
12707a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    struct stat input_stat;
12717a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    memset(&input_stat, 0, sizeof(input_stat));
12727a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    if (stat(apk_path, &input_stat) != 0) {
12737a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        PLOG(ERROR) << "Could not stat " << apk_path << " during dexopt";
12747a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        return;
12757a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    }
12767a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle
12777a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    struct utimbuf ut;
12787a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    ut.actime = input_stat.st_atime;
12797a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    ut.modtime = input_stat.st_mtime;
12807a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    if (utime(out_oat_path, &ut) != 0) {
12817a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        PLOG(WARNING) << "Could not update access times for " << apk_path << " during dexopt";
12827a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    }
12837a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle}
12847a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle
128580a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle// Runs (execv) dexoptanalyzer on the given arguments.
1286114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle// The analyzer will check if the dex_file needs to be (re)compiled to match the compiler_filter.
1287114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle// If this is for a profile guided compilation, profile_was_updated will tell whether or not
1288114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle// the profile has changed.
1289114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravlestatic void exec_dexoptanalyzer(const std::string& dex_file, const char* instruction_set,
1290114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        const char* compiler_filter, bool profile_was_updated) {
129180a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    static const char* DEXOPTANALYZER_BIN = "/system/bin/dexoptanalyzer";
129280a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
129380a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
129480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
129580a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        ALOGE("Instruction set %s longer than max length of %d",
129680a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle              instruction_set, MAX_INSTRUCTION_SET_LEN);
129780a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        return;
129880a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    }
129980a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
130080a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    char dex_file_arg[strlen("--dex-file=") + PKG_PATH_MAX];
130180a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    char isa_arg[strlen("--isa=") + MAX_INSTRUCTION_SET_LEN];
130280a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    char compiler_filter_arg[strlen("--compiler-filter=") + kPropertyValueMax];
1303114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    const char* assume_profile_changed = "--assume-profile-changed";
130480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
1305114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    sprintf(dex_file_arg, "--dex-file=%s", dex_file.c_str());
130680a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    sprintf(isa_arg, "--isa=%s", instruction_set);
130780a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    sprintf(compiler_filter_arg, "--compiler-filter=%s", compiler_filter);
130880a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
130980a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    // program name, dex file, isa, filter, the final NULL
1310114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    const char* argv[5 + (profile_was_updated ? 1 : 0)];
131180a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    int i = 0;
131280a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    argv[i++] = DEXOPTANALYZER_BIN;
131380a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    argv[i++] = dex_file_arg;
131480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    argv[i++] = isa_arg;
131580a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    argv[i++] = compiler_filter_arg;
1316114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    if (profile_was_updated) {
1317114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        argv[i++] = assume_profile_changed;
1318114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    }
131980a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    argv[i] = NULL;
132080a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
132180a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    execv(DEXOPTANALYZER_BIN, (char * const *)argv);
132280a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    ALOGE("execv(%s) failed: %s\n", DEXOPTANALYZER_BIN, strerror(errno));
132380a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle}
132480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
132580a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle// Prepares the oat dir for the secondary dex files.
1326114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravlestatic bool prepare_secondary_dex_oat_dir(const std::string& dex_path, int uid,
1327114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        const char* instruction_set, std::string* oat_dir_out) {
1328114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    unsigned long dirIndex = dex_path.rfind('/');
132980a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    if (dirIndex == std::string::npos) {
1330c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        LOG(ERROR ) << "Unexpected dir structure for secondary dex " << dex_path;
133180a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        return false;
133280a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    }
1333114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    std::string dex_dir = dex_path.substr(0, dirIndex);
133480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
133580a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    // Create oat file output directory.
1336ebc8a79bbc00759307bed9142b60cff1e35d79e0Calin Juravle    mode_t oat_dir_mode = S_IRWXU | S_IRWXG | S_IXOTH;
1337ebc8a79bbc00759307bed9142b60cff1e35d79e0Calin Juravle    if (prepare_app_cache_dir(dex_dir, "oat", oat_dir_mode, uid, uid) != 0) {
1338c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        LOG(ERROR) << "Could not prepare oat dir for secondary dex: " << dex_path;
133980a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        return false;
134080a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    }
134180a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
134280a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    char oat_dir[PKG_PATH_MAX];
1343114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    snprintf(oat_dir, PKG_PATH_MAX, "%s/oat", dex_dir.c_str());
134480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    oat_dir_out->assign(oat_dir);
134580a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
134680a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    // Create oat/isa output directory.
1347ebc8a79bbc00759307bed9142b60cff1e35d79e0Calin Juravle    if (prepare_app_cache_dir(*oat_dir_out, instruction_set, oat_dir_mode, uid, uid) != 0) {
1348c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        LOG(ERROR) << "Could not prepare oat/isa dir for secondary dex: " << dex_path;
134980a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        return false;
135080a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    }
135180a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
135280a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    return true;
135380a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle}
135480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
135580a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravlestatic int constexpr DEXOPTANALYZER_BIN_EXEC_ERROR = 200;
135680a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
135780a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle// Verifies the result of dexoptanalyzer executed for the apk_path.
135880a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle// If the result is valid returns true and sets dexopt_needed_out to a valid value.
135980a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle// Returns false for errors or unexpected result values.
1360114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravlestatic bool process_dexoptanalyzer_result(const std::string& dex_path, int result,
136180a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle            int* dexopt_needed_out) {
136280a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    // The result values are defined in dexoptanalyzer.
136380a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    switch (result) {
136480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        case 0:  // no_dexopt_needed
136580a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle            *dexopt_needed_out = NO_DEXOPT_NEEDED; return true;
136680a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        case 1:  // dex2oat_from_scratch
136780a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle            *dexopt_needed_out = DEX2OAT_FROM_SCRATCH; return true;
136880a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        case 5:  // dex2oat_for_bootimage_odex
136980a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle            *dexopt_needed_out = -DEX2OAT_FOR_BOOT_IMAGE; return true;
137080a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        case 6:  // dex2oat_for_filter_odex
137180a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle            *dexopt_needed_out = -DEX2OAT_FOR_FILTER; return true;
137280a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        case 7:  // dex2oat_for_relocation_odex
137380a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle            *dexopt_needed_out = -DEX2OAT_FOR_RELOCATION; return true;
137480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        case 2:  // dex2oat_for_bootimage_oat
137580a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        case 3:  // dex2oat_for_filter_oat
137680a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        case 4:  // dex2oat_for_relocation_oat
1377c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle            LOG(ERROR) << "Dexoptnalyzer return the status of an oat file."
1378c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle                    << " Expected odex file status for secondary dex " << dex_path
137980a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle                    << " : dexoptanalyzer result=" << result;
138080a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle            return false;
138180a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        default:
1382c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle            LOG(ERROR) << "Unexpected result for dexoptanalyzer " << dex_path
138380a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle                    << " exec_dexoptanalyzer result=" << result;
138480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle            return false;
138580a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    }
138680a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle}
138780a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
1388c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle// Processes the dex_path as a secondary dex files and return true if the path dex file should
138980a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle// be compiled. Returns false for errors (logged) or true if the secondary dex path was process
139080a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle// successfully.
1391ebc8a79bbc00759307bed9142b60cff1e35d79e0Calin Juravle// When returning true, the output parameters will be:
1392ebc8a79bbc00759307bed9142b60cff1e35d79e0Calin Juravle//   - is_public_out: whether or not the oat file should not be made public
1393ebc8a79bbc00759307bed9142b60cff1e35d79e0Calin Juravle//   - dexopt_needed_out: valid OatFileAsssitant::DexOptNeeded
1394ebc8a79bbc00759307bed9142b60cff1e35d79e0Calin Juravle//   - oat_dir_out: the oat dir path where the oat file should be stored
1395ebc8a79bbc00759307bed9142b60cff1e35d79e0Calin Juravle//   - dex_path_out: the real path of the dex file
1396114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravlestatic bool process_secondary_dex_dexopt(const char* original_dex_path, const char* pkgname,
139780a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        int dexopt_flags, const char* volume_uuid, int uid, const char* instruction_set,
1398ebc8a79bbc00759307bed9142b60cff1e35d79e0Calin Juravle        const char* compiler_filter, bool* is_public_out, int* dexopt_needed_out,
1399ebc8a79bbc00759307bed9142b60cff1e35d79e0Calin Juravle        std::string* oat_dir_out, std::string* dex_path_out) {
140080a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    int storage_flag;
140180a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
140280a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    if ((dexopt_flags & DEXOPT_STORAGE_CE) != 0) {
140380a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        storage_flag = FLAG_STORAGE_CE;
140480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        if ((dexopt_flags & DEXOPT_STORAGE_DE) != 0) {
140580a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle            LOG(ERROR) << "Ambiguous secondary dex storage flag. Both, CE and DE, flags are set";
140680a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle            return false;
140780a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        }
140880a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    } else if ((dexopt_flags & DEXOPT_STORAGE_DE) != 0) {
140980a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        storage_flag = FLAG_STORAGE_DE;
141080a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    } else {
141180a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        LOG(ERROR) << "Secondary dex storage flag must be set";
141280a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        return false;
141380a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    }
141480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
1415114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    {
1416114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        // As opposed to the primary apk, secondary dex files might contain symlinks.
1417114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        // Resolve the path before passing it to the validate method to
1418114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        // make sure the verification is done on the real location.
1419114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        UniqueCPtr<char> dex_real_path_cstr(realpath(original_dex_path, nullptr));
1420114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        if (dex_real_path_cstr == nullptr) {
1421114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            PLOG(ERROR) << "Could not get the real path of the secondary dex file "
1422114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle                    << original_dex_path;
1423114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            return false;
1424114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        } else {
1425114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            dex_path_out->assign(dex_real_path_cstr.get());
1426114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        }
1427114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    }
1428114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    const std::string& dex_path = *dex_path_out;
1429c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid, uid, storage_flag)) {
1430c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
143180a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        return false;
143280a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    }
143380a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
143480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    // Check if the path exist. If not, there's nothing to do.
1435ebc8a79bbc00759307bed9142b60cff1e35d79e0Calin Juravle    struct stat dex_path_stat;
1436ebc8a79bbc00759307bed9142b60cff1e35d79e0Calin Juravle    if (stat(dex_path.c_str(), &dex_path_stat) != 0) {
143780a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        if (errno == ENOENT) {
143880a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle            // Secondary dex files might be deleted any time by the app.
143980a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle            // Nothing to do if that's the case
1440114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            ALOGV("Secondary dex does not exist %s", dex_path.c_str());
144180a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle            return NO_DEXOPT_NEEDED;
144280a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        } else {
1443c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle            PLOG(ERROR) << "Could not access secondary dex " << dex_path;
144480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        }
144580a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    }
144680a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
1447ebc8a79bbc00759307bed9142b60cff1e35d79e0Calin Juravle    // Check if we should make the oat file public.
1448ebc8a79bbc00759307bed9142b60cff1e35d79e0Calin Juravle    // Note that if the dex file is not public the compiled code cannot be made public.
1449ebc8a79bbc00759307bed9142b60cff1e35d79e0Calin Juravle    *is_public_out = ((dexopt_flags & DEXOPT_PUBLIC) != 0) &&
1450ebc8a79bbc00759307bed9142b60cff1e35d79e0Calin Juravle            ((dex_path_stat.st_mode & S_IROTH) != 0);
1451ebc8a79bbc00759307bed9142b60cff1e35d79e0Calin Juravle
145280a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    // Prepare the oat directories.
1453114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    if (!prepare_secondary_dex_oat_dir(dex_path, uid, instruction_set, oat_dir_out)) {
145480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        return false;
145580a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    }
145680a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
1457114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    // Analyze profiles.
1458114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    bool profile_was_updated = analyze_profiles(uid, dex_path, /*is_secondary_dex*/true);
1459114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle
146080a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    pid_t pid = fork();
146180a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    if (pid == 0) {
146280a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        // child -- drop privileges before continuing.
146380a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        drop_capabilities(uid);
146480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        // Run dexoptanalyzer to get dexopt_needed code.
1465114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle        exec_dexoptanalyzer(dex_path, instruction_set, compiler_filter, profile_was_updated);
146680a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        exit(DEXOPTANALYZER_BIN_EXEC_ERROR);
146780a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    }
146880a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
146980a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    /* parent */
147080a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
147180a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    int result = wait_child(pid);
147280a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    if (!WIFEXITED(result)) {
1473c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        LOG(ERROR) << "dexoptanalyzer failed for path " << dex_path << ": " << result;
147480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        return false;
147580a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    }
147680a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    result = WEXITSTATUS(result);
1477c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    bool success = process_dexoptanalyzer_result(dex_path, result, dexopt_needed_out);
147880a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    // Run dexopt only if needed or forced.
147980a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    // Note that dexoptanalyzer is executed even if force compilation is enabled.
148080a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    // We ignore its valid dexopNeeded result, but still check (in process_dexoptanalyzer_result)
148180a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    // that we only get results for odex files (apk_dir/oat/isa/code.odex) and not
148280a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    // for oat files from dalvik-cache.
148380a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    if (success && ((dexopt_flags & DEXOPT_FORCE) != 0)) {
148480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        *dexopt_needed_out = DEX2OAT_FROM_SCRATCH;
148580a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    }
148680a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
148780a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    return success;
148880a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle}
148980a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
1490c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravleint dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* instruction_set,
149180a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
1492cb556e340b50d16e8fac41b0c69d8d35bd7915f9Calin Juravle        const char* volume_uuid, const char* shared_libraries, const char* se_info) {
14937a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    CHECK(pkgname != nullptr);
14947a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    CHECK(pkgname[0] != 0);
14957a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    if ((dexopt_flags & ~DEXOPT_MASK) != 0) {
14967a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        LOG_FATAL("dexopt flags contains unknown fields\n");
14977a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    }
14987a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle
1499ebc8a79bbc00759307bed9142b60cff1e35d79e0Calin Juravle    bool is_public = (dexopt_flags & DEXOPT_PUBLIC) != 0;
15007a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    bool debuggable = (dexopt_flags & DEXOPT_DEBUGGABLE) != 0;
15017a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    bool boot_complete = (dexopt_flags & DEXOPT_BOOTCOMPLETE) != 0;
15027a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    bool profile_guided = (dexopt_flags & DEXOPT_PROFILE_GUIDED) != 0;
150380a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    bool is_secondary_dex = (dexopt_flags & DEXOPT_SECONDARY_DEX) != 0;
150480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle
150580a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    // Check if we're dealing with a secondary dex file and if we need to compile it.
150680a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    std::string oat_dir_str;
1507114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    std::string dex_real_path;
150880a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    if (is_secondary_dex) {
1509c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        if (process_secondary_dex_dexopt(dex_path, pkgname, dexopt_flags, volume_uuid, uid,
1510ebc8a79bbc00759307bed9142b60cff1e35d79e0Calin Juravle                instruction_set, compiler_filter, &is_public, &dexopt_needed, &oat_dir_str,
1511ebc8a79bbc00759307bed9142b60cff1e35d79e0Calin Juravle                &dex_real_path)) {
151280a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle            oat_dir = oat_dir_str.c_str();
1513114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            dex_path = dex_real_path.c_str();
151480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle            if (dexopt_needed == NO_DEXOPT_NEEDED) {
151580a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle                return 0;  // Nothing to do, report success.
151680a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle            }
151780a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        } else {
151880a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle            return -1;  // We had an error, logged in the process method.
151980a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        }
152080a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    } else {
1521c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        // Currently these flags are only use for secondary dex files.
1522c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        // Verify that they are not set for primary apks.
152380a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        CHECK((dexopt_flags & DEXOPT_STORAGE_CE) == 0);
152480a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle        CHECK((dexopt_flags & DEXOPT_STORAGE_DE) == 0);
152580a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    }
15267a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle
15277a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    // Open the input file.
15281a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle    unique_fd input_fd(open(dex_path, O_RDONLY, 0));
15297a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    if (input_fd.get() < 0) {
1530c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        ALOGE("installd cannot open '%s' for input during dexopt\n", dex_path);
153190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return -1;
153290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
153390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
15347a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    // Create the output OAT file.
15357a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    char out_oat_path[PKG_PATH_MAX];
1536c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    Dex2oatFileWrapper out_oat_fd = open_oat_out_file(dex_path, oat_dir, is_public, uid,
153780a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle            instruction_set, is_secondary_dex, out_oat_path);
15387a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    if (out_oat_fd.get() < 0) {
15397a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        return -1;
154090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
154190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
15427a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    // Open vdex files.
15437a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    Dex2oatFileWrapper in_vdex_fd;
15447a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    Dex2oatFileWrapper out_vdex_fd;
1545575fc2c3c8f67be2a258cf28f915c7c902f332d1Nicolas Geoffray    if (!open_vdex_files(dex_path, out_oat_path, dexopt_needed, instruction_set, is_public, uid,
154676689e9b20ff5d377fb33eaa23edcad9300d5fc4Nicolas Geoffray            is_secondary_dex, profile_guided, &in_vdex_fd, &out_vdex_fd)) {
15477a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle        return -1;
154890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
154990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
1550cb556e340b50d16e8fac41b0c69d8d35bd7915f9Calin Juravle    // Ensure that the oat dir and the compiler artifacts of secondary dex files have the correct
1551cb556e340b50d16e8fac41b0c69d8d35bd7915f9Calin Juravle    // selinux context (we generate them on the fly during the dexopt invocation and they don't
1552cb556e340b50d16e8fac41b0c69d8d35bd7915f9Calin Juravle    // fully inherit their parent context).
1553cb556e340b50d16e8fac41b0c69d8d35bd7915f9Calin Juravle    // Note that for primary apk the oat files are created before, in a separate installd
1554cb556e340b50d16e8fac41b0c69d8d35bd7915f9Calin Juravle    // call which also does the restorecon. TODO(calin): unify the paths.
1555cb556e340b50d16e8fac41b0c69d8d35bd7915f9Calin Juravle    if (is_secondary_dex) {
1556cb556e340b50d16e8fac41b0c69d8d35bd7915f9Calin Juravle        if (selinux_android_restorecon_pkgdir(oat_dir, se_info, uid,
1557cb556e340b50d16e8fac41b0c69d8d35bd7915f9Calin Juravle                SELINUX_ANDROID_RESTORECON_RECURSE)) {
1558cb556e340b50d16e8fac41b0c69d8d35bd7915f9Calin Juravle            LOG(ERROR) << "Failed to restorecon " << oat_dir;
1559cb556e340b50d16e8fac41b0c69d8d35bd7915f9Calin Juravle            return -1;
1560cb556e340b50d16e8fac41b0c69d8d35bd7915f9Calin Juravle        }
1561cb556e340b50d16e8fac41b0c69d8d35bd7915f9Calin Juravle    }
1562cb556e340b50d16e8fac41b0c69d8d35bd7915f9Calin Juravle
15637a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    // Create a swap file if necessary.
15641a0af3b982b851519b06233addaa9c3bcb61f627Calin Juravle    unique_fd swap_fd = maybe_open_dexopt_swap_file(out_oat_path);
15657a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle
15667a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    // Create the app image file if needed.
15677a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    Dex2oatFileWrapper image_fd =
15682289c0ac89acce109b3e93c434d86b20c5ecc1adCalin Juravle            maybe_open_app_image(out_oat_path, profile_guided, is_public, uid, is_secondary_dex);
15697a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle
15707a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    // Open the reference profile if needed.
1571114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle    Dex2oatFileWrapper reference_profile_fd = maybe_open_reference_profile(
1572114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            pkgname, dex_path, profile_guided, is_public, uid, is_secondary_dex);
15737a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle
1574c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    ALOGV("DexInv: --- BEGIN '%s' ---\n", dex_path);
157590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
157690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    pid_t pid = fork();
157790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (pid == 0) {
157890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        /* child -- drop privileges before continuing */
157990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        drop_capabilities(uid);
158090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
158176cc027ca6ebfd2f870c1cbb8f1d1fd19e0ac8e9Richard Uhler        SetDex2OatScheduling(boot_complete);
158290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (flock(out_oat_fd.get(), LOCK_EX | LOCK_NB) != 0) {
158390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            ALOGE("flock(%s) failed: %s\n", out_oat_path, strerror(errno));
158490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            _exit(67);
158590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
158690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
158776cc027ca6ebfd2f870c1cbb8f1d1fd19e0ac8e9Richard Uhler        run_dex2oat(input_fd.get(),
158876cc027ca6ebfd2f870c1cbb8f1d1fd19e0ac8e9Richard Uhler                    out_oat_fd.get(),
158976cc027ca6ebfd2f870c1cbb8f1d1fd19e0ac8e9Richard Uhler                    in_vdex_fd.get(),
15907a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle                    out_vdex_fd.get(),
159176cc027ca6ebfd2f870c1cbb8f1d1fd19e0ac8e9Richard Uhler                    image_fd.get(),
159210b8a6e72c5b1c2eef4e5657dd0927f0c1623fffJeff Hao                    dex_path,
159376cc027ca6ebfd2f870c1cbb8f1d1fd19e0ac8e9Richard Uhler                    out_oat_path,
159476cc027ca6ebfd2f870c1cbb8f1d1fd19e0ac8e9Richard Uhler                    swap_fd.get(),
159576cc027ca6ebfd2f870c1cbb8f1d1fd19e0ac8e9Richard Uhler                    instruction_set,
159676cc027ca6ebfd2f870c1cbb8f1d1fd19e0ac8e9Richard Uhler                    compiler_filter,
159776cc027ca6ebfd2f870c1cbb8f1d1fd19e0ac8e9Richard Uhler                    debuggable,
159876cc027ca6ebfd2f870c1cbb8f1d1fd19e0ac8e9Richard Uhler                    boot_complete,
159976cc027ca6ebfd2f870c1cbb8f1d1fd19e0ac8e9Richard Uhler                    reference_profile_fd.get(),
160076cc027ca6ebfd2f870c1cbb8f1d1fd19e0ac8e9Richard Uhler                    shared_libraries);
160190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        _exit(68);   /* only get here on exec failure */
160290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    } else {
160390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        int res = wait_child(pid);
160490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (res == 0) {
1605c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle            ALOGV("DexInv: --- END '%s' (success) ---\n", dex_path);
160690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        } else {
1607c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle            ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", dex_path, res);
1608013f02e58b0b17b5b9fb4b4a2b3dc482eecfc434Andreas Gampe            return res;
160990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
161090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
161190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
1612c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    update_out_oat_access_times(dex_path, out_oat_path);
161390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
161490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // We've been successful, don't delete output.
161590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    out_oat_fd.SetCleanup(false);
16167a570e8a0091a93be7dfd98acbb693bbb6ace75aCalin Juravle    out_vdex_fd.SetCleanup(false);
161790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    image_fd.SetCleanup(false);
161890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    reference_profile_fd.SetCleanup(false);
161990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
162090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    return 0;
162190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
162290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
1623c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle// Try to remove the given directory. Log an error if the directory exists
1624c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle// and is empty but could not be removed.
1625c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravlestatic bool rmdir_if_empty(const char* dir) {
1626c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    if (rmdir(dir) == 0) {
1627c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        return true;
1628c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    }
1629c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    if (errno == ENOENT || errno == ENOTEMPTY) {
1630c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        return true;
1631c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    }
1632c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    PLOG(ERROR) << "Failed to remove dir: " << dir;
1633c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    return false;
1634c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle}
1635c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle
1636c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle// Try to unlink the given file. Log an error if the file exists and could not
1637c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle// be unlinked.
1638c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravlestatic bool unlink_if_exists(const std::string& file) {
1639c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    if (unlink(file.c_str()) == 0) {
1640c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        return true;
1641c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    }
1642c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    if (errno == ENOENT) {
1643c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        return true;
1644c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle
1645c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    }
1646c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    PLOG(ERROR) << "Could not unlink: " << file;
1647c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    return false;
1648c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle}
1649c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle
1650c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle// Create the oat file structure for the secondary dex 'dex_path' and assign
1651c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle// the individual path component to the 'out_' parameters.
1652c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravlestatic bool create_secondary_dex_oat_layout(const std::string& dex_path, const std::string& isa,
1653c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        /*out*/char* out_oat_dir, /*out*/char* out_oat_isa_dir, /*out*/char* out_oat_path) {
1654c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    size_t dirIndex = dex_path.rfind('/');
1655c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    if (dirIndex == std::string::npos) {
1656c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        LOG(ERROR) << "Unexpected dir structure for dex file " << dex_path;
1657c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        return false;
1658c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    }
1659c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    // TODO(calin): we have similar computations in at lest 3 other places
1660c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    // (InstalldNativeService, otapropt and dexopt). Unify them and get rid of snprintf by
1661c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    // use string append.
1662c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    std::string apk_dir = dex_path.substr(0, dirIndex);
1663c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    snprintf(out_oat_dir, PKG_PATH_MAX, "%s/oat", apk_dir.c_str());
1664c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    snprintf(out_oat_isa_dir, PKG_PATH_MAX, "%s/%s", out_oat_dir, isa.c_str());
1665c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle
1666c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    if (!create_oat_out_path(dex_path.c_str(), isa.c_str(), out_oat_dir,
1667114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            /*is_secondary_dex*/true, out_oat_path)) {
1668c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        LOG(ERROR) << "Could not create oat path for secondary dex " << dex_path;
1669c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        return false;
1670c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    }
1671c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    return true;
1672c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle}
1673c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle
1674c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle// Reconcile the secondary dex 'dex_path' and its generated oat files.
1675c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle// Return true if all the parameters are valid and the secondary dex file was
1676c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle//   processed successfully (i.e. the dex_path either exists, or if not, its corresponding
1677c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle//   oat/vdex/art files where deleted successfully). In this case, out_secondary_dex_exists
1678c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle//   will be true if the secondary dex file still exists. If the secondary dex file does not exist,
1679c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle//   the method cleans up any previously generated compiler artifacts (oat, vdex, art).
1680c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle// Return false if there were errors during processing. In this case
1681c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle//   out_secondary_dex_exists will be set to false.
1682c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravlebool reconcile_secondary_dex_file(const std::string& dex_path,
1683c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        const std::string& pkgname, int uid, const std::vector<std::string>& isas,
1684c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        const std::unique_ptr<std::string>& volume_uuid, int storage_flag,
1685c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        /*out*/bool* out_secondary_dex_exists) {
1686c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    // Set out to false to start with, just in case we have validation errors.
1687c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    *out_secondary_dex_exists = false;
1688c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    if (isas.size() == 0) {
1689c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        LOG(ERROR) << "reconcile_secondary_dex_file called with empty isas vector";
1690c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        return false;
1691c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    }
1692c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle
1693c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    const char* volume_uuid_cstr = volume_uuid == nullptr ? nullptr : volume_uuid->c_str();
1694c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    if (!validate_secondary_dex_path(pkgname.c_str(), dex_path.c_str(), volume_uuid_cstr,
1695c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle            uid, storage_flag)) {
1696c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
1697c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        return false;
1698c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    }
1699c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle
1700c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    if (access(dex_path.c_str(), F_OK) == 0) {
1701c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        // The path exists, nothing to do. The odex files (if any) will be left untouched.
1702c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        *out_secondary_dex_exists = true;
1703c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        return true;
1704c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    } else if (errno != ENOENT) {
1705c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        PLOG(ERROR) << "Failed to check access to secondary dex " << dex_path;
1706c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        return false;
1707c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    }
1708c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle
1709c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    // The secondary dex does not exist anymore. Clear any generated files.
1710c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    char oat_path[PKG_PATH_MAX];
1711c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    char oat_dir[PKG_PATH_MAX];
1712c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    char oat_isa_dir[PKG_PATH_MAX];
1713c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    bool result = true;
1714c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    for (size_t i = 0; i < isas.size(); i++) {
1715c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        if (!create_secondary_dex_oat_layout(dex_path, isas[i], oat_dir, oat_isa_dir, oat_path)) {
1716c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle            LOG(ERROR) << "Could not create secondary odex layout: " << dex_path;
1717c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle            result = false;
1718c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle            continue;
1719c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        }
1720513140941eeec7a5bad56956cce101f3da829d43Calin Juravle
1721513140941eeec7a5bad56956cce101f3da829d43Calin Juravle        // Delete oat/vdex/art files.
1722c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        result = unlink_if_exists(oat_path) && result;
1723c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        result = unlink_if_exists(create_vdex_filename(oat_path)) && result;
1724c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        result = unlink_if_exists(create_image_filename(oat_path)) && result;
1725c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle
1726513140941eeec7a5bad56956cce101f3da829d43Calin Juravle        // Delete profiles.
1727513140941eeec7a5bad56956cce101f3da829d43Calin Juravle        std::string current_profile = create_current_profile_path(
1728513140941eeec7a5bad56956cce101f3da829d43Calin Juravle                multiuser_get_user_id(uid), dex_path, /*is_secondary*/true);
1729513140941eeec7a5bad56956cce101f3da829d43Calin Juravle        std::string reference_profile = create_reference_profile_path(
1730513140941eeec7a5bad56956cce101f3da829d43Calin Juravle                dex_path, /*is_secondary*/true);
1731513140941eeec7a5bad56956cce101f3da829d43Calin Juravle        result = unlink_if_exists(current_profile) && result;
1732513140941eeec7a5bad56956cce101f3da829d43Calin Juravle        result = unlink_if_exists(reference_profile) && result;
1733513140941eeec7a5bad56956cce101f3da829d43Calin Juravle
1734c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        // Try removing the directories as well, they might be empty.
1735c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        result = rmdir_if_empty(oat_isa_dir) && result;
1736c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle        result = rmdir_if_empty(oat_dir) && result;
1737c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    }
1738c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle
1739c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle    return result;
1740c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle}
1741c9eab382fa4d71ade0077e0547969a47f39ecf05Calin Juravle
174290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey// Helper for move_ab, so that we can have common failure-case cleanup.
174390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic bool unlink_and_rename(const char* from, const char* to) {
174490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // Check whether "from" exists, and if so whether it's regular. If it is, unlink. Otherwise,
174590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // return a failure.
174690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    struct stat s;
174790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (stat(to, &s) == 0) {
174890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (!S_ISREG(s.st_mode)) {
174990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            LOG(ERROR) << from << " is not a regular file to replace for A/B.";
175090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            return false;
175190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
175290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (unlink(to) != 0) {
175390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            LOG(ERROR) << "Could not unlink " << to << " to move A/B.";
175490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            return false;
175590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
175690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    } else {
175790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        // This may be a permission problem. We could investigate the error code, but we'll just
175890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        // let the rename failure do the work for us.
175990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
176090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
176190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // Try to rename "to" to "from."
176290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (rename(from, to) != 0) {
176390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        PLOG(ERROR) << "Could not rename " << from << " to " << to;
176490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return false;
176590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
176690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    return true;
176790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
176890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
176990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey// Move/rename a B artifact (from) to an A artifact (to).
177090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeystatic bool move_ab_path(const std::string& b_path, const std::string& a_path) {
177190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // Check whether B exists.
177290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    {
177390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        struct stat s;
177490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (stat(b_path.c_str(), &s) != 0) {
177590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            // Silently ignore for now. The service calling this isn't smart enough to understand
177690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            // lack of artifacts at the moment.
177790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            return false;
177890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
177990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (!S_ISREG(s.st_mode)) {
178090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            LOG(ERROR) << "A/B artifact " << b_path << " is not a regular file.";
178190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            // Try to unlink, but swallow errors.
178290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            unlink(b_path.c_str());
178390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            return false;
178490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
178590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
178690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
178790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // Rename B to A.
178890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (!unlink_and_rename(b_path.c_str(), a_path.c_str())) {
178990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        // Delete the b_path so we don't try again (or fail earlier).
179090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (unlink(b_path.c_str()) != 0) {
179190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            PLOG(ERROR) << "Could not unlink " << b_path;
179290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
179390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
179490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return false;
179590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
179690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
179790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    return true;
179890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
179990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
180090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeybool move_ab(const char* apk_path, const char* instruction_set, const char* oat_dir) {
180190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // Get the current slot suffix. No suffix, no A/B.
180290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    std::string slot_suffix;
180390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    {
180490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        char buf[kPropertyValueMax];
180590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (get_property("ro.boot.slot_suffix", buf, nullptr) <= 0) {
180690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            return false;
180790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
180890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        slot_suffix = buf;
180990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
181090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (!ValidateTargetSlotSuffix(slot_suffix)) {
181190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            LOG(ERROR) << "Target slot suffix not legal: " << slot_suffix;
181290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            return false;
181390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
181490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
181590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
181690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // Validate other inputs.
181790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (validate_apk_path(apk_path) != 0) {
181890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        LOG(ERROR) << "Invalid apk_path: " << apk_path;
181990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return false;
182090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
182190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (validate_apk_path(oat_dir) != 0) {
182290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        LOG(ERROR) << "Invalid oat_dir: " << oat_dir;
182390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return false;
182490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
182590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
182690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    char a_path[PKG_PATH_MAX];
182790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (!calculate_oat_file_path(a_path, oat_dir, apk_path, instruction_set)) {
182890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return false;
182990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
183090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    const std::string a_vdex_path = create_vdex_filename(a_path);
183190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    const std::string a_image_path = create_image_filename(a_path);
183290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
183390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // B path = A path + slot suffix.
183490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    const std::string b_path = StringPrintf("%s.%s", a_path, slot_suffix.c_str());
183590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    const std::string b_vdex_path = StringPrintf("%s.%s", a_vdex_path.c_str(), slot_suffix.c_str());
183690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    const std::string b_image_path = StringPrintf("%s.%s",
183790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                                                  a_image_path.c_str(),
183890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                                                  slot_suffix.c_str());
183990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
184090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool success = true;
184190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    if (move_ab_path(b_path, a_path)) {
184290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (move_ab_path(b_vdex_path, a_vdex_path)) {
184390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            // Note: we can live without an app image. As such, ignore failure to move the image file.
184490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            //       If we decide to require the app image, or the app image being moved correctly,
184590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            //       then change accordingly.
184690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            constexpr bool kIgnoreAppImageFailure = true;
184790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
184890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            if (!a_image_path.empty()) {
184990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                if (!move_ab_path(b_image_path, a_image_path)) {
185090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                    unlink(a_image_path.c_str());
185190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                    if (!kIgnoreAppImageFailure) {
185290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                        success = false;
185390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                    }
185490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                }
185590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            }
185690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        } else {
185790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            // Cleanup: delete B image, ignore errors.
185890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            unlink(b_image_path.c_str());
185990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            success = false;
186090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
186190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    } else {
186290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        // Cleanup: delete B image, ignore errors.
186390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        unlink(b_vdex_path.c_str());
186490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        unlink(b_image_path.c_str());
186590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        success = false;
186690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
186790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    return success;
186890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
186990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
187090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkeybool delete_odex(const char* apk_path, const char* instruction_set, const char* oat_dir) {
187190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // Delete the oat/odex file.
187290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    char out_path[PKG_PATH_MAX];
187380a2125b85eaa0916daea7e90b016fe4f1b59924Calin Juravle    if (!create_oat_out_path(apk_path, instruction_set, oat_dir,
1874114f08107be384a3f9cc954bdec2b6b7619354aeCalin Juravle            /*is_secondary_dex*/false, out_path)) {
187590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return false;
187690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    }
187790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
187890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // In case of a permission failure report the issue. Otherwise just print a warning.
187990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    auto unlink_and_check = [](const char* path) -> bool {
188090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        int result = unlink(path);
188190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        if (result != 0) {
188290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            if (errno == EACCES || errno == EPERM) {
188390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                PLOG(ERROR) << "Could not unlink " << path;
188490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey                return false;
188590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            }
188690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey            PLOG(WARNING) << "Could not unlink " << path;
188790aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        }
188890aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey        return true;
188990aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    };
189090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
189190aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // Delete the oat/odex file.
189290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool return_value_oat = unlink_and_check(out_path);
189390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
189490aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // Derive and delete the app image.
189590aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    bool return_value_art = unlink_and_check(create_image_filename(out_path).c_str());
189690aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
18973040d9db984237259c0ec7238ad9081018ffe808Nicolas Geoffray    // Derive and delete the vdex file.
18983040d9db984237259c0ec7238ad9081018ffe808Nicolas Geoffray    bool return_value_vdex = unlink_and_check(create_vdex_filename(out_path).c_str());
18993040d9db984237259c0ec7238ad9081018ffe808Nicolas Geoffray
190090aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey    // Report success.
19013040d9db984237259c0ec7238ad9081018ffe808Nicolas Geoffray    return return_value_oat && return_value_art && return_value_vdex;
190290aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey}
190390aff26f0135379db19432ae90c40c0831ba5954Jeff Sharkey
19046c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey}  // namespace installd
19056c2c056193010cf93b4264810d462c120ce801c8Jeff Sharkey}  // namespace android
1906