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