xref: /aosp_15_r20/art/artd/artd.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2021 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "artd.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include <fcntl.h>
20*795d594fSAndroid Build Coastguard Worker #include <sys/inotify.h>
21*795d594fSAndroid Build Coastguard Worker #include <sys/mount.h>
22*795d594fSAndroid Build Coastguard Worker #include <sys/poll.h>
23*795d594fSAndroid Build Coastguard Worker #include <sys/stat.h>
24*795d594fSAndroid Build Coastguard Worker #include <sys/types.h>
25*795d594fSAndroid Build Coastguard Worker #include <unistd.h>
26*795d594fSAndroid Build Coastguard Worker 
27*795d594fSAndroid Build Coastguard Worker #include <climits>
28*795d594fSAndroid Build Coastguard Worker #include <csignal>
29*795d594fSAndroid Build Coastguard Worker #include <cstddef>
30*795d594fSAndroid Build Coastguard Worker #include <cstdint>
31*795d594fSAndroid Build Coastguard Worker #include <cstdlib>
32*795d594fSAndroid Build Coastguard Worker #include <cstring>
33*795d594fSAndroid Build Coastguard Worker #include <filesystem>
34*795d594fSAndroid Build Coastguard Worker #include <functional>
35*795d594fSAndroid Build Coastguard Worker #include <iterator>
36*795d594fSAndroid Build Coastguard Worker #include <map>
37*795d594fSAndroid Build Coastguard Worker #include <memory>
38*795d594fSAndroid Build Coastguard Worker #include <mutex>
39*795d594fSAndroid Build Coastguard Worker #include <new>
40*795d594fSAndroid Build Coastguard Worker #include <optional>
41*795d594fSAndroid Build Coastguard Worker #include <ostream>
42*795d594fSAndroid Build Coastguard Worker #include <regex>
43*795d594fSAndroid Build Coastguard Worker #include <string>
44*795d594fSAndroid Build Coastguard Worker #include <string_view>
45*795d594fSAndroid Build Coastguard Worker #include <system_error>
46*795d594fSAndroid Build Coastguard Worker #include <type_traits>
47*795d594fSAndroid Build Coastguard Worker #include <unordered_set>
48*795d594fSAndroid Build Coastguard Worker #include <utility>
49*795d594fSAndroid Build Coastguard Worker #include <vector>
50*795d594fSAndroid Build Coastguard Worker 
51*795d594fSAndroid Build Coastguard Worker #include "aidl/com/android/server/art/ArtConstants.h"
52*795d594fSAndroid Build Coastguard Worker #include "aidl/com/android/server/art/BnArtd.h"
53*795d594fSAndroid Build Coastguard Worker #include "aidl/com/android/server/art/DexoptTrigger.h"
54*795d594fSAndroid Build Coastguard Worker #include "aidl/com/android/server/art/IArtdCancellationSignal.h"
55*795d594fSAndroid Build Coastguard Worker #include "aidl/com/android/server/art/IArtdNotification.h"
56*795d594fSAndroid Build Coastguard Worker #include "android-base/errors.h"
57*795d594fSAndroid Build Coastguard Worker #include "android-base/file.h"
58*795d594fSAndroid Build Coastguard Worker #include "android-base/logging.h"
59*795d594fSAndroid Build Coastguard Worker #include "android-base/parseint.h"
60*795d594fSAndroid Build Coastguard Worker #include "android-base/result.h"
61*795d594fSAndroid Build Coastguard Worker #include "android-base/scopeguard.h"
62*795d594fSAndroid Build Coastguard Worker #include "android-base/strings.h"
63*795d594fSAndroid Build Coastguard Worker #include "android-base/unique_fd.h"
64*795d594fSAndroid Build Coastguard Worker #include "android/binder_auto_utils.h"
65*795d594fSAndroid Build Coastguard Worker #include "android/binder_interface_utils.h"
66*795d594fSAndroid Build Coastguard Worker #include "android/binder_manager.h"
67*795d594fSAndroid Build Coastguard Worker #include "android/binder_process.h"
68*795d594fSAndroid Build Coastguard Worker #include "base/compiler_filter.h"
69*795d594fSAndroid Build Coastguard Worker #include "base/file_magic.h"
70*795d594fSAndroid Build Coastguard Worker #include "base/file_utils.h"
71*795d594fSAndroid Build Coastguard Worker #include "base/globals.h"
72*795d594fSAndroid Build Coastguard Worker #include "base/logging.h"
73*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
74*795d594fSAndroid Build Coastguard Worker #include "base/mem_map.h"
75*795d594fSAndroid Build Coastguard Worker #include "base/memfd.h"
76*795d594fSAndroid Build Coastguard Worker #include "base/os.h"
77*795d594fSAndroid Build Coastguard Worker #include "base/pidfd.h"
78*795d594fSAndroid Build Coastguard Worker #include "base/time_utils.h"
79*795d594fSAndroid Build Coastguard Worker #include "base/zip_archive.h"
80*795d594fSAndroid Build Coastguard Worker #include "cmdline_types.h"
81*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_loader.h"
82*795d594fSAndroid Build Coastguard Worker #include "exec_utils.h"
83*795d594fSAndroid Build Coastguard Worker #include "file_utils.h"
84*795d594fSAndroid Build Coastguard Worker #include "fstab/fstab.h"
85*795d594fSAndroid Build Coastguard Worker #include "oat/oat_file_assistant.h"
86*795d594fSAndroid Build Coastguard Worker #include "oat/oat_file_assistant_context.h"
87*795d594fSAndroid Build Coastguard Worker #include "odrefresh/odrefresh.h"
88*795d594fSAndroid Build Coastguard Worker #include "path_utils.h"
89*795d594fSAndroid Build Coastguard Worker #include "profman/profman_result.h"
90*795d594fSAndroid Build Coastguard Worker #include "selinux/android.h"
91*795d594fSAndroid Build Coastguard Worker #include "service.h"
92*795d594fSAndroid Build Coastguard Worker #include "tools/binder_utils.h"
93*795d594fSAndroid Build Coastguard Worker #include "tools/cmdline_builder.h"
94*795d594fSAndroid Build Coastguard Worker #include "tools/tools.h"
95*795d594fSAndroid Build Coastguard Worker 
96*795d594fSAndroid Build Coastguard Worker namespace art {
97*795d594fSAndroid Build Coastguard Worker namespace artd {
98*795d594fSAndroid Build Coastguard Worker 
99*795d594fSAndroid Build Coastguard Worker namespace {
100*795d594fSAndroid Build Coastguard Worker 
101*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::ArtConstants;
102*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::ArtdDexoptResult;
103*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::ArtifactsLocation;
104*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::ArtifactsPath;
105*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::CopyAndRewriteProfileResult;
106*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::DexMetadataPath;
107*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::DexoptOptions;
108*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::DexoptTrigger;
109*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::FileVisibility;
110*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::FsPermission;
111*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::GetDexoptNeededResult;
112*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::GetDexoptStatusResult;
113*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::IArtdCancellationSignal;
114*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::IArtdNotification;
115*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::MergeProfileOptions;
116*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::OutputArtifacts;
117*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::OutputProfile;
118*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::PriorityClass;
119*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::ProfilePath;
120*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::RuntimeArtifactsPath;
121*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::VdexPath;
122*795d594fSAndroid Build Coastguard Worker using ::android::base::Basename;
123*795d594fSAndroid Build Coastguard Worker using ::android::base::Dirname;
124*795d594fSAndroid Build Coastguard Worker using ::android::base::ErrnoError;
125*795d594fSAndroid Build Coastguard Worker using ::android::base::Error;
126*795d594fSAndroid Build Coastguard Worker using ::android::base::Join;
127*795d594fSAndroid Build Coastguard Worker using ::android::base::make_scope_guard;
128*795d594fSAndroid Build Coastguard Worker using ::android::base::ParseInt;
129*795d594fSAndroid Build Coastguard Worker using ::android::base::ReadFileToString;
130*795d594fSAndroid Build Coastguard Worker using ::android::base::Result;
131*795d594fSAndroid Build Coastguard Worker using ::android::base::Split;
132*795d594fSAndroid Build Coastguard Worker using ::android::base::Tokenize;
133*795d594fSAndroid Build Coastguard Worker using ::android::base::Trim;
134*795d594fSAndroid Build Coastguard Worker using ::android::base::unique_fd;
135*795d594fSAndroid Build Coastguard Worker using ::android::base::WriteStringToFd;
136*795d594fSAndroid Build Coastguard Worker using ::android::base::WriteStringToFile;
137*795d594fSAndroid Build Coastguard Worker using ::android::fs_mgr::FstabEntry;
138*795d594fSAndroid Build Coastguard Worker using ::art::service::ValidateClassLoaderContext;
139*795d594fSAndroid Build Coastguard Worker using ::art::service::ValidateDexPath;
140*795d594fSAndroid Build Coastguard Worker using ::art::tools::CmdlineBuilder;
141*795d594fSAndroid Build Coastguard Worker using ::art::tools::Fatal;
142*795d594fSAndroid Build Coastguard Worker using ::art::tools::GetProcMountsAncestorsOfPath;
143*795d594fSAndroid Build Coastguard Worker using ::art::tools::NonFatal;
144*795d594fSAndroid Build Coastguard Worker using ::ndk::ScopedAStatus;
145*795d594fSAndroid Build Coastguard Worker 
146*795d594fSAndroid Build Coastguard Worker using PrimaryCurProfilePath = ProfilePath::PrimaryCurProfilePath;
147*795d594fSAndroid Build Coastguard Worker using TmpProfilePath = ProfilePath::TmpProfilePath;
148*795d594fSAndroid Build Coastguard Worker using WritableProfilePath = ProfilePath::WritableProfilePath;
149*795d594fSAndroid Build Coastguard Worker 
150*795d594fSAndroid Build Coastguard Worker constexpr const char* kServiceName = "artd";
151*795d594fSAndroid Build Coastguard Worker constexpr const char* kPreRebootServiceName = "artd_pre_reboot";
152*795d594fSAndroid Build Coastguard Worker constexpr const char* kArtdCancellationSignalType = "ArtdCancellationSignal";
153*795d594fSAndroid Build Coastguard Worker constexpr const char* kDefaultPreRebootTmpDir = "/mnt/artd_tmp";
154*795d594fSAndroid Build Coastguard Worker 
155*795d594fSAndroid Build Coastguard Worker // Timeout for short operations, such as merging profiles.
156*795d594fSAndroid Build Coastguard Worker constexpr int kShortTimeoutSec = 60;  // 1 minute.
157*795d594fSAndroid Build Coastguard Worker 
158*795d594fSAndroid Build Coastguard Worker // Timeout for long operations, such as compilation. We set it to be smaller than the Package
159*795d594fSAndroid Build Coastguard Worker // Manager watchdog (PackageManagerService.WATCHDOG_TIMEOUT, 10 minutes), so that if the operation
160*795d594fSAndroid Build Coastguard Worker // is called from the Package Manager's thread handler, it will be aborted before that watchdog
161*795d594fSAndroid Build Coastguard Worker // would take down the system server.
162*795d594fSAndroid Build Coastguard Worker constexpr int kLongTimeoutSec = 570;  // 9.5 minutes.
163*795d594fSAndroid Build Coastguard Worker 
GetSize(std::string_view path)164*795d594fSAndroid Build Coastguard Worker std::optional<int64_t> GetSize(std::string_view path) {
165*795d594fSAndroid Build Coastguard Worker   std::error_code ec;
166*795d594fSAndroid Build Coastguard Worker   int64_t size = std::filesystem::file_size(path, ec);
167*795d594fSAndroid Build Coastguard Worker   if (ec) {
168*795d594fSAndroid Build Coastguard Worker     // It is okay if the file does not exist. We don't have to log it.
169*795d594fSAndroid Build Coastguard Worker     if (ec.value() != ENOENT) {
170*795d594fSAndroid Build Coastguard Worker       LOG(ERROR) << ART_FORMAT("Failed to get the file size of '{}': {}", path, ec.message());
171*795d594fSAndroid Build Coastguard Worker     }
172*795d594fSAndroid Build Coastguard Worker     return std::nullopt;
173*795d594fSAndroid Build Coastguard Worker   }
174*795d594fSAndroid Build Coastguard Worker   return size;
175*795d594fSAndroid Build Coastguard Worker }
176*795d594fSAndroid Build Coastguard Worker 
DeleteFile(const std::string & path)177*795d594fSAndroid Build Coastguard Worker bool DeleteFile(const std::string& path) {
178*795d594fSAndroid Build Coastguard Worker   std::error_code ec;
179*795d594fSAndroid Build Coastguard Worker   std::filesystem::remove(path, ec);
180*795d594fSAndroid Build Coastguard Worker   if (ec) {
181*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << ART_FORMAT("Failed to remove '{}': {}", path, ec.message());
182*795d594fSAndroid Build Coastguard Worker     return false;
183*795d594fSAndroid Build Coastguard Worker   }
184*795d594fSAndroid Build Coastguard Worker   return true;
185*795d594fSAndroid Build Coastguard Worker }
186*795d594fSAndroid Build Coastguard Worker 
187*795d594fSAndroid Build Coastguard Worker // Deletes a file. Returns the size of the deleted file, or 0 if the deleted file is empty or an
188*795d594fSAndroid Build Coastguard Worker // error occurs.
GetSizeAndDeleteFile(const std::string & path)189*795d594fSAndroid Build Coastguard Worker int64_t GetSizeAndDeleteFile(const std::string& path) {
190*795d594fSAndroid Build Coastguard Worker   std::optional<int64_t> size = GetSize(path);
191*795d594fSAndroid Build Coastguard Worker   if (!size.has_value()) {
192*795d594fSAndroid Build Coastguard Worker     return 0;
193*795d594fSAndroid Build Coastguard Worker   }
194*795d594fSAndroid Build Coastguard Worker   if (!DeleteFile(path)) {
195*795d594fSAndroid Build Coastguard Worker     return 0;
196*795d594fSAndroid Build Coastguard Worker   }
197*795d594fSAndroid Build Coastguard Worker   return size.value();
198*795d594fSAndroid Build Coastguard Worker }
199*795d594fSAndroid Build Coastguard Worker 
ParseCompilerFilter(const std::string & compiler_filter_str)200*795d594fSAndroid Build Coastguard Worker Result<CompilerFilter::Filter> ParseCompilerFilter(const std::string& compiler_filter_str) {
201*795d594fSAndroid Build Coastguard Worker   CompilerFilter::Filter compiler_filter;
202*795d594fSAndroid Build Coastguard Worker   if (!CompilerFilter::ParseCompilerFilter(compiler_filter_str.c_str(), &compiler_filter)) {
203*795d594fSAndroid Build Coastguard Worker     return Errorf("Failed to parse compiler filter '{}'", compiler_filter_str);
204*795d594fSAndroid Build Coastguard Worker   }
205*795d594fSAndroid Build Coastguard Worker   return compiler_filter;
206*795d594fSAndroid Build Coastguard Worker }
207*795d594fSAndroid Build Coastguard Worker 
DexOptTriggerFromAidl(int32_t aidl_value)208*795d594fSAndroid Build Coastguard Worker OatFileAssistant::DexOptTrigger DexOptTriggerFromAidl(int32_t aidl_value) {
209*795d594fSAndroid Build Coastguard Worker   OatFileAssistant::DexOptTrigger trigger{};
210*795d594fSAndroid Build Coastguard Worker   if ((aidl_value & static_cast<int32_t>(DexoptTrigger::COMPILER_FILTER_IS_BETTER)) != 0) {
211*795d594fSAndroid Build Coastguard Worker     trigger.targetFilterIsBetter = true;
212*795d594fSAndroid Build Coastguard Worker   }
213*795d594fSAndroid Build Coastguard Worker   if ((aidl_value & static_cast<int32_t>(DexoptTrigger::COMPILER_FILTER_IS_SAME)) != 0) {
214*795d594fSAndroid Build Coastguard Worker     trigger.targetFilterIsSame = true;
215*795d594fSAndroid Build Coastguard Worker   }
216*795d594fSAndroid Build Coastguard Worker   if ((aidl_value & static_cast<int32_t>(DexoptTrigger::COMPILER_FILTER_IS_WORSE)) != 0) {
217*795d594fSAndroid Build Coastguard Worker     trigger.targetFilterIsWorse = true;
218*795d594fSAndroid Build Coastguard Worker   }
219*795d594fSAndroid Build Coastguard Worker   if ((aidl_value & static_cast<int32_t>(DexoptTrigger::PRIMARY_BOOT_IMAGE_BECOMES_USABLE)) != 0) {
220*795d594fSAndroid Build Coastguard Worker     trigger.primaryBootImageBecomesUsable = true;
221*795d594fSAndroid Build Coastguard Worker   }
222*795d594fSAndroid Build Coastguard Worker   if ((aidl_value & static_cast<int32_t>(DexoptTrigger::NEED_EXTRACTION)) != 0) {
223*795d594fSAndroid Build Coastguard Worker     trigger.needExtraction = true;
224*795d594fSAndroid Build Coastguard Worker   }
225*795d594fSAndroid Build Coastguard Worker   return trigger;
226*795d594fSAndroid Build Coastguard Worker }
227*795d594fSAndroid Build Coastguard Worker 
ArtifactsLocationToAidl(OatFileAssistant::Location location)228*795d594fSAndroid Build Coastguard Worker ArtifactsLocation ArtifactsLocationToAidl(OatFileAssistant::Location location) {
229*795d594fSAndroid Build Coastguard Worker   switch (location) {
230*795d594fSAndroid Build Coastguard Worker     case OatFileAssistant::Location::kLocationNoneOrError:
231*795d594fSAndroid Build Coastguard Worker       return ArtifactsLocation::NONE_OR_ERROR;
232*795d594fSAndroid Build Coastguard Worker     case OatFileAssistant::Location::kLocationOat:
233*795d594fSAndroid Build Coastguard Worker       return ArtifactsLocation::DALVIK_CACHE;
234*795d594fSAndroid Build Coastguard Worker     case OatFileAssistant::Location::kLocationOdex:
235*795d594fSAndroid Build Coastguard Worker       return ArtifactsLocation::NEXT_TO_DEX;
236*795d594fSAndroid Build Coastguard Worker     case OatFileAssistant::Location::kLocationDm:
237*795d594fSAndroid Build Coastguard Worker       return ArtifactsLocation::DM;
238*795d594fSAndroid Build Coastguard Worker       // No default. All cases should be explicitly handled, or the compilation will fail.
239*795d594fSAndroid Build Coastguard Worker   }
240*795d594fSAndroid Build Coastguard Worker   // This should never happen. Just in case we get a non-enumerator value.
241*795d594fSAndroid Build Coastguard Worker   LOG(FATAL) << "Unexpected Location " << location;
242*795d594fSAndroid Build Coastguard Worker }
243*795d594fSAndroid Build Coastguard Worker 
CreateDir(const std::string & path)244*795d594fSAndroid Build Coastguard Worker Result<bool> CreateDir(const std::string& path) {
245*795d594fSAndroid Build Coastguard Worker   std::error_code ec;
246*795d594fSAndroid Build Coastguard Worker   bool created = std::filesystem::create_directory(path, ec);
247*795d594fSAndroid Build Coastguard Worker   if (ec) {
248*795d594fSAndroid Build Coastguard Worker     return Errorf("Failed to create directory '{}': {}", path, ec.message());
249*795d594fSAndroid Build Coastguard Worker   }
250*795d594fSAndroid Build Coastguard Worker   return created;
251*795d594fSAndroid Build Coastguard Worker }
252*795d594fSAndroid Build Coastguard Worker 
PrepareArtifactsDir(const std::string & path,const FsPermission & fs_permission)253*795d594fSAndroid Build Coastguard Worker Result<void> PrepareArtifactsDir(const std::string& path, const FsPermission& fs_permission) {
254*795d594fSAndroid Build Coastguard Worker   bool created = OR_RETURN(CreateDir(path));
255*795d594fSAndroid Build Coastguard Worker 
256*795d594fSAndroid Build Coastguard Worker   auto cleanup = make_scope_guard([&] {
257*795d594fSAndroid Build Coastguard Worker     if (created) {
258*795d594fSAndroid Build Coastguard Worker       std::error_code ec;
259*795d594fSAndroid Build Coastguard Worker       std::filesystem::remove(path, ec);
260*795d594fSAndroid Build Coastguard Worker     }
261*795d594fSAndroid Build Coastguard Worker   });
262*795d594fSAndroid Build Coastguard Worker 
263*795d594fSAndroid Build Coastguard Worker   if (chmod(path.c_str(), DirFsPermissionToMode(fs_permission)) != 0) {
264*795d594fSAndroid Build Coastguard Worker     return ErrnoErrorf("Failed to chmod directory '{}'", path);
265*795d594fSAndroid Build Coastguard Worker   }
266*795d594fSAndroid Build Coastguard Worker   OR_RETURN(Chown(path, fs_permission));
267*795d594fSAndroid Build Coastguard Worker 
268*795d594fSAndroid Build Coastguard Worker   cleanup.Disable();
269*795d594fSAndroid Build Coastguard Worker   return {};
270*795d594fSAndroid Build Coastguard Worker }
271*795d594fSAndroid Build Coastguard Worker 
PrepareArtifactsDirs(const OutputArtifacts & output_artifacts,std::string * oat_dir_path)272*795d594fSAndroid Build Coastguard Worker Result<void> PrepareArtifactsDirs(const OutputArtifacts& output_artifacts,
273*795d594fSAndroid Build Coastguard Worker                                   /*out*/ std::string* oat_dir_path) {
274*795d594fSAndroid Build Coastguard Worker   if (output_artifacts.artifactsPath.isInDalvikCache) {
275*795d594fSAndroid Build Coastguard Worker     return {};
276*795d594fSAndroid Build Coastguard Worker   }
277*795d594fSAndroid Build Coastguard Worker 
278*795d594fSAndroid Build Coastguard Worker   std::filesystem::path oat_path(
279*795d594fSAndroid Build Coastguard Worker       OR_RETURN(BuildArtifactsPath(output_artifacts.artifactsPath)).oat_path);
280*795d594fSAndroid Build Coastguard Worker   std::filesystem::path isa_dir = oat_path.parent_path();
281*795d594fSAndroid Build Coastguard Worker   std::filesystem::path oat_dir = isa_dir.parent_path();
282*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(oat_dir.filename(), "oat");
283*795d594fSAndroid Build Coastguard Worker 
284*795d594fSAndroid Build Coastguard Worker   OR_RETURN(PrepareArtifactsDir(oat_dir, output_artifacts.permissionSettings.dirFsPermission));
285*795d594fSAndroid Build Coastguard Worker   OR_RETURN(PrepareArtifactsDir(isa_dir, output_artifacts.permissionSettings.dirFsPermission));
286*795d594fSAndroid Build Coastguard Worker   *oat_dir_path = oat_dir;
287*795d594fSAndroid Build Coastguard Worker   return {};
288*795d594fSAndroid Build Coastguard Worker }
289*795d594fSAndroid Build Coastguard Worker 
GetFileVisibility(const std::string & file)290*795d594fSAndroid Build Coastguard Worker Result<FileVisibility> GetFileVisibility(const std::string& file) {
291*795d594fSAndroid Build Coastguard Worker   std::error_code ec;
292*795d594fSAndroid Build Coastguard Worker   std::filesystem::file_status status = std::filesystem::status(file, ec);
293*795d594fSAndroid Build Coastguard Worker   if (!std::filesystem::status_known(status)) {
294*795d594fSAndroid Build Coastguard Worker     return Errorf("Failed to get status of '{}': {}", file, ec.message());
295*795d594fSAndroid Build Coastguard Worker   }
296*795d594fSAndroid Build Coastguard Worker   if (!std::filesystem::exists(status)) {
297*795d594fSAndroid Build Coastguard Worker     return FileVisibility::NOT_FOUND;
298*795d594fSAndroid Build Coastguard Worker   }
299*795d594fSAndroid Build Coastguard Worker 
300*795d594fSAndroid Build Coastguard Worker   return (status.permissions() & std::filesystem::perms::others_read) !=
301*795d594fSAndroid Build Coastguard Worker                  std::filesystem::perms::none ?
302*795d594fSAndroid Build Coastguard Worker              FileVisibility::OTHER_READABLE :
303*795d594fSAndroid Build Coastguard Worker              FileVisibility::NOT_OTHER_READABLE;
304*795d594fSAndroid Build Coastguard Worker }
305*795d594fSAndroid Build Coastguard Worker 
ToArtdCancellationSignal(IArtdCancellationSignal * input)306*795d594fSAndroid Build Coastguard Worker Result<ArtdCancellationSignal*> ToArtdCancellationSignal(IArtdCancellationSignal* input) {
307*795d594fSAndroid Build Coastguard Worker   if (input == nullptr) {
308*795d594fSAndroid Build Coastguard Worker     return Error() << "Cancellation signal must not be nullptr";
309*795d594fSAndroid Build Coastguard Worker   }
310*795d594fSAndroid Build Coastguard Worker   // We cannot use `dynamic_cast` because ART code is compiled with `-fno-rtti`, so we have to check
311*795d594fSAndroid Build Coastguard Worker   // the magic number.
312*795d594fSAndroid Build Coastguard Worker   int64_t type;
313*795d594fSAndroid Build Coastguard Worker   if (!input->getType(&type).isOk() ||
314*795d594fSAndroid Build Coastguard Worker       type != reinterpret_cast<intptr_t>(kArtdCancellationSignalType)) {
315*795d594fSAndroid Build Coastguard Worker     // The cancellation signal must be created by `Artd::createCancellationSignal`.
316*795d594fSAndroid Build Coastguard Worker     return Error() << "Invalid cancellation signal type";
317*795d594fSAndroid Build Coastguard Worker   }
318*795d594fSAndroid Build Coastguard Worker   return static_cast<ArtdCancellationSignal*>(input);
319*795d594fSAndroid Build Coastguard Worker }
320*795d594fSAndroid Build Coastguard Worker 
CopyFile(const std::string & src_path,const NewFile & dst_file)321*795d594fSAndroid Build Coastguard Worker Result<void> CopyFile(const std::string& src_path, const NewFile& dst_file) {
322*795d594fSAndroid Build Coastguard Worker   std::string content;
323*795d594fSAndroid Build Coastguard Worker   if (!ReadFileToString(src_path, &content)) {
324*795d594fSAndroid Build Coastguard Worker     return Errorf("Failed to read file '{}': {}", src_path, strerror(errno));
325*795d594fSAndroid Build Coastguard Worker   }
326*795d594fSAndroid Build Coastguard Worker   if (!WriteStringToFd(content, dst_file.Fd())) {
327*795d594fSAndroid Build Coastguard Worker     return Errorf("Failed to write file '{}': {}", dst_file.TempPath(), strerror(errno));
328*795d594fSAndroid Build Coastguard Worker   }
329*795d594fSAndroid Build Coastguard Worker   if (fsync(dst_file.Fd()) != 0) {
330*795d594fSAndroid Build Coastguard Worker     return Errorf("Failed to flush file '{}': {}", dst_file.TempPath(), strerror(errno));
331*795d594fSAndroid Build Coastguard Worker   }
332*795d594fSAndroid Build Coastguard Worker   if (lseek(dst_file.Fd(), /*offset=*/0, SEEK_SET) != 0) {
333*795d594fSAndroid Build Coastguard Worker     return Errorf(
334*795d594fSAndroid Build Coastguard Worker         "Failed to reset the offset for file '{}': {}", dst_file.TempPath(), strerror(errno));
335*795d594fSAndroid Build Coastguard Worker   }
336*795d594fSAndroid Build Coastguard Worker   return {};
337*795d594fSAndroid Build Coastguard Worker }
338*795d594fSAndroid Build Coastguard Worker 
SetLogVerbosity()339*795d594fSAndroid Build Coastguard Worker Result<void> SetLogVerbosity() {
340*795d594fSAndroid Build Coastguard Worker   std::string options =
341*795d594fSAndroid Build Coastguard Worker       android::base::GetProperty("dalvik.vm.artd-verbose", /*default_value=*/"oat");
342*795d594fSAndroid Build Coastguard Worker   if (options.empty()) {
343*795d594fSAndroid Build Coastguard Worker     return {};
344*795d594fSAndroid Build Coastguard Worker   }
345*795d594fSAndroid Build Coastguard Worker 
346*795d594fSAndroid Build Coastguard Worker   CmdlineType<LogVerbosity> parser;
347*795d594fSAndroid Build Coastguard Worker   CmdlineParseResult<LogVerbosity> result = parser.Parse(options);
348*795d594fSAndroid Build Coastguard Worker   if (!result.IsSuccess()) {
349*795d594fSAndroid Build Coastguard Worker     return Error() << result.GetMessage();
350*795d594fSAndroid Build Coastguard Worker   }
351*795d594fSAndroid Build Coastguard Worker 
352*795d594fSAndroid Build Coastguard Worker   gLogVerbosity = result.ReleaseValue();
353*795d594fSAndroid Build Coastguard Worker   return {};
354*795d594fSAndroid Build Coastguard Worker }
355*795d594fSAndroid Build Coastguard Worker 
AnalyzeCopyAndRewriteProfileFailure(File * src,ProfmanResult::CopyAndUpdateResult result)356*795d594fSAndroid Build Coastguard Worker CopyAndRewriteProfileResult AnalyzeCopyAndRewriteProfileFailure(
357*795d594fSAndroid Build Coastguard Worker     File* src, ProfmanResult::CopyAndUpdateResult result) {
358*795d594fSAndroid Build Coastguard Worker   DCHECK(result == ProfmanResult::kCopyAndUpdateNoMatch ||
359*795d594fSAndroid Build Coastguard Worker          result == ProfmanResult::kCopyAndUpdateErrorFailedToLoadProfile);
360*795d594fSAndroid Build Coastguard Worker 
361*795d594fSAndroid Build Coastguard Worker   auto bad_profile = [&](std::string_view error_msg) {
362*795d594fSAndroid Build Coastguard Worker     return CopyAndRewriteProfileResult{
363*795d594fSAndroid Build Coastguard Worker         .status = CopyAndRewriteProfileResult::Status::BAD_PROFILE,
364*795d594fSAndroid Build Coastguard Worker         .errorMsg = ART_FORMAT("Failed to load profile '{}': {}", src->GetPath(), error_msg)};
365*795d594fSAndroid Build Coastguard Worker   };
366*795d594fSAndroid Build Coastguard Worker   CopyAndRewriteProfileResult no_profile{.status = CopyAndRewriteProfileResult::Status::NO_PROFILE,
367*795d594fSAndroid Build Coastguard Worker                                          .errorMsg = ""};
368*795d594fSAndroid Build Coastguard Worker 
369*795d594fSAndroid Build Coastguard Worker   int64_t length = src->GetLength();
370*795d594fSAndroid Build Coastguard Worker   if (length < 0) {
371*795d594fSAndroid Build Coastguard Worker     return bad_profile(strerror(-length));
372*795d594fSAndroid Build Coastguard Worker   }
373*795d594fSAndroid Build Coastguard Worker   if (length == 0) {
374*795d594fSAndroid Build Coastguard Worker     return no_profile;
375*795d594fSAndroid Build Coastguard Worker   }
376*795d594fSAndroid Build Coastguard Worker 
377*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
378*795d594fSAndroid Build Coastguard Worker   uint32_t magic;
379*795d594fSAndroid Build Coastguard Worker   if (!ReadMagicAndReset(src->Fd(), &magic, &error_msg)) {
380*795d594fSAndroid Build Coastguard Worker     return bad_profile(error_msg);
381*795d594fSAndroid Build Coastguard Worker   }
382*795d594fSAndroid Build Coastguard Worker   if (IsZipMagic(magic)) {
383*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<ZipArchive> zip_archive(
384*795d594fSAndroid Build Coastguard Worker         ZipArchive::OpenFromOwnedFd(src->Fd(), src->GetPath().c_str(), &error_msg));
385*795d594fSAndroid Build Coastguard Worker     if (zip_archive == nullptr) {
386*795d594fSAndroid Build Coastguard Worker       return bad_profile(error_msg);
387*795d594fSAndroid Build Coastguard Worker     }
388*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<ZipEntry> zip_entry(
389*795d594fSAndroid Build Coastguard Worker         zip_archive->Find(ArtConstants::DEX_METADATA_PROFILE_ENTRY, &error_msg));
390*795d594fSAndroid Build Coastguard Worker     if (zip_entry == nullptr || zip_entry->GetUncompressedLength() == 0) {
391*795d594fSAndroid Build Coastguard Worker       return no_profile;
392*795d594fSAndroid Build Coastguard Worker     }
393*795d594fSAndroid Build Coastguard Worker   }
394*795d594fSAndroid Build Coastguard Worker 
395*795d594fSAndroid Build Coastguard Worker   if (result == ProfmanResult::kCopyAndUpdateNoMatch) {
396*795d594fSAndroid Build Coastguard Worker     return bad_profile(
397*795d594fSAndroid Build Coastguard Worker         "The profile does not match the APK (The checksums in the profile do not match the "
398*795d594fSAndroid Build Coastguard Worker         "checksums of the .dex files in the APK)");
399*795d594fSAndroid Build Coastguard Worker   }
400*795d594fSAndroid Build Coastguard Worker   return bad_profile("The profile is in the wrong format or an I/O error has occurred");
401*795d594fSAndroid Build Coastguard Worker }
402*795d594fSAndroid Build Coastguard Worker 
403*795d594fSAndroid Build Coastguard Worker // Returns the fd on success, or an invalid fd if the dex file contains no profile, or error if any
404*795d594fSAndroid Build Coastguard Worker // error occurs.
ExtractEmbeddedProfileToFd(const std::string & dex_path)405*795d594fSAndroid Build Coastguard Worker Result<File> ExtractEmbeddedProfileToFd(const std::string& dex_path) {
406*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<File> dex_file = OR_RETURN(OpenFileForReading(dex_path));
407*795d594fSAndroid Build Coastguard Worker 
408*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
409*795d594fSAndroid Build Coastguard Worker   uint32_t magic;
410*795d594fSAndroid Build Coastguard Worker   if (!ReadMagicAndReset(dex_file->Fd(), &magic, &error_msg)) {
411*795d594fSAndroid Build Coastguard Worker     return Error() << error_msg;
412*795d594fSAndroid Build Coastguard Worker   }
413*795d594fSAndroid Build Coastguard Worker   if (!IsZipMagic(magic)) {
414*795d594fSAndroid Build Coastguard Worker     if (DexFileLoader::IsMagicValid(magic)) {
415*795d594fSAndroid Build Coastguard Worker       // The dex file can be a plain dex file. This is expected.
416*795d594fSAndroid Build Coastguard Worker       return File();
417*795d594fSAndroid Build Coastguard Worker     }
418*795d594fSAndroid Build Coastguard Worker     return Error() << "File is neither a zip file nor a plain dex file";
419*795d594fSAndroid Build Coastguard Worker   }
420*795d594fSAndroid Build Coastguard Worker 
421*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<ZipArchive> zip_archive(
422*795d594fSAndroid Build Coastguard Worker       ZipArchive::OpenFromOwnedFd(dex_file->Fd(), dex_path.c_str(), &error_msg));
423*795d594fSAndroid Build Coastguard Worker   if (zip_archive == nullptr) {
424*795d594fSAndroid Build Coastguard Worker     return Error() << error_msg;
425*795d594fSAndroid Build Coastguard Worker   }
426*795d594fSAndroid Build Coastguard Worker   constexpr const char* kEmbeddedProfileEntry = "assets/art-profile/baseline.prof";
427*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<ZipEntry> zip_entry(zip_archive->Find(kEmbeddedProfileEntry, &error_msg));
428*795d594fSAndroid Build Coastguard Worker   size_t size;
429*795d594fSAndroid Build Coastguard Worker   if (zip_entry == nullptr || (size = zip_entry->GetUncompressedLength()) == 0) {
430*795d594fSAndroid Build Coastguard Worker     // From system/libziparchive/zip_error.cpp.
431*795d594fSAndroid Build Coastguard Worker     constexpr const char* kEntryNotFound = "Entry not found";
432*795d594fSAndroid Build Coastguard Worker     if (error_msg != kEntryNotFound) {
433*795d594fSAndroid Build Coastguard Worker       LOG(WARNING) << ART_FORMAT(
434*795d594fSAndroid Build Coastguard Worker           "Failed to find zip entry '{}' in '{}': {}", kEmbeddedProfileEntry, dex_path, error_msg);
435*795d594fSAndroid Build Coastguard Worker     }
436*795d594fSAndroid Build Coastguard Worker     // The dex file doesn't necessarily contain a profile. This is expected.
437*795d594fSAndroid Build Coastguard Worker     return File();
438*795d594fSAndroid Build Coastguard Worker   }
439*795d594fSAndroid Build Coastguard Worker 
440*795d594fSAndroid Build Coastguard Worker   // The name is for debugging only.
441*795d594fSAndroid Build Coastguard Worker   std::string memfd_name =
442*795d594fSAndroid Build Coastguard Worker       ART_FORMAT("{} extracted in memory from {}", kEmbeddedProfileEntry, dex_path);
443*795d594fSAndroid Build Coastguard Worker   File memfd(memfd_create(memfd_name.c_str(), /*flags=*/0),
444*795d594fSAndroid Build Coastguard Worker              memfd_name,
445*795d594fSAndroid Build Coastguard Worker              /*check_usage=*/false);
446*795d594fSAndroid Build Coastguard Worker   if (!memfd.IsValid()) {
447*795d594fSAndroid Build Coastguard Worker     return ErrnoError() << "Failed to create memfd";
448*795d594fSAndroid Build Coastguard Worker   }
449*795d594fSAndroid Build Coastguard Worker   if (ftruncate(memfd.Fd(), size) != 0) {
450*795d594fSAndroid Build Coastguard Worker     return ErrnoError() << "Failed to ftruncate memfd";
451*795d594fSAndroid Build Coastguard Worker   }
452*795d594fSAndroid Build Coastguard Worker   // Map with MAP_SHARED because we're feeding the fd to profman.
453*795d594fSAndroid Build Coastguard Worker   MemMap mem_map = MemMap::MapFile(size,
454*795d594fSAndroid Build Coastguard Worker                                    PROT_READ | PROT_WRITE,
455*795d594fSAndroid Build Coastguard Worker                                    MAP_SHARED,
456*795d594fSAndroid Build Coastguard Worker                                    memfd.Fd(),
457*795d594fSAndroid Build Coastguard Worker                                    /*start=*/0,
458*795d594fSAndroid Build Coastguard Worker                                    /*low_4gb=*/false,
459*795d594fSAndroid Build Coastguard Worker                                    memfd_name.c_str(),
460*795d594fSAndroid Build Coastguard Worker                                    &error_msg);
461*795d594fSAndroid Build Coastguard Worker   if (!mem_map.IsValid()) {
462*795d594fSAndroid Build Coastguard Worker     return Errorf("Failed to mmap memfd: {}", error_msg);
463*795d594fSAndroid Build Coastguard Worker   }
464*795d594fSAndroid Build Coastguard Worker   if (!zip_entry->ExtractToMemory(mem_map.Begin(), &error_msg)) {
465*795d594fSAndroid Build Coastguard Worker     return Errorf("Failed to extract '{}': {}", kEmbeddedProfileEntry, error_msg);
466*795d594fSAndroid Build Coastguard Worker   }
467*795d594fSAndroid Build Coastguard Worker 
468*795d594fSAndroid Build Coastguard Worker   // Reopen the memfd with readonly to make SELinux happy when the fd is passed to a child process
469*795d594fSAndroid Build Coastguard Worker   // who doesn't have write permission. (b/303909581)
470*795d594fSAndroid Build Coastguard Worker   std::string path = ART_FORMAT("/proc/self/fd/{}", memfd.Fd());
471*795d594fSAndroid Build Coastguard Worker   // NOLINTNEXTLINE - O_CLOEXEC is omitted on purpose
472*795d594fSAndroid Build Coastguard Worker   File memfd_readonly(open(path.c_str(), O_RDONLY),
473*795d594fSAndroid Build Coastguard Worker                       memfd_name,
474*795d594fSAndroid Build Coastguard Worker                       /*check_usage=*/false,
475*795d594fSAndroid Build Coastguard Worker                       /*read_only_mode=*/true);
476*795d594fSAndroid Build Coastguard Worker   if (!memfd_readonly.IsOpened()) {
477*795d594fSAndroid Build Coastguard Worker     return ErrnoErrorf("Failed to open file '{}' ('{}')", path, memfd_name);
478*795d594fSAndroid Build Coastguard Worker   }
479*795d594fSAndroid Build Coastguard Worker 
480*795d594fSAndroid Build Coastguard Worker   return memfd_readonly;
481*795d594fSAndroid Build Coastguard Worker }
482*795d594fSAndroid Build Coastguard Worker 
483*795d594fSAndroid Build Coastguard Worker class FdLogger {
484*795d594fSAndroid Build Coastguard Worker  public:
Add(const NewFile & file)485*795d594fSAndroid Build Coastguard Worker   void Add(const NewFile& file) { fd_mapping_.emplace_back(file.Fd(), file.TempPath()); }
Add(const File & file)486*795d594fSAndroid Build Coastguard Worker   void Add(const File& file) { fd_mapping_.emplace_back(file.Fd(), file.GetPath()); }
487*795d594fSAndroid Build Coastguard Worker 
GetFds()488*795d594fSAndroid Build Coastguard Worker   std::string GetFds() {
489*795d594fSAndroid Build Coastguard Worker     std::vector<int> fds;
490*795d594fSAndroid Build Coastguard Worker     fds.reserve(fd_mapping_.size());
491*795d594fSAndroid Build Coastguard Worker     for (const auto& [fd, path] : fd_mapping_) {
492*795d594fSAndroid Build Coastguard Worker       fds.push_back(fd);
493*795d594fSAndroid Build Coastguard Worker     }
494*795d594fSAndroid Build Coastguard Worker     return Join(fds, ':');
495*795d594fSAndroid Build Coastguard Worker   }
496*795d594fSAndroid Build Coastguard Worker 
497*795d594fSAndroid Build Coastguard Worker  private:
498*795d594fSAndroid Build Coastguard Worker   std::vector<std::pair<int, std::string>> fd_mapping_;
499*795d594fSAndroid Build Coastguard Worker 
500*795d594fSAndroid Build Coastguard Worker   friend std::ostream& operator<<(std::ostream& os, const FdLogger& fd_logger);
501*795d594fSAndroid Build Coastguard Worker };
502*795d594fSAndroid Build Coastguard Worker 
operator <<(std::ostream & os,const FdLogger & fd_logger)503*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const FdLogger& fd_logger) {
504*795d594fSAndroid Build Coastguard Worker   for (const auto& [fd, path] : fd_logger.fd_mapping_) {
505*795d594fSAndroid Build Coastguard Worker     os << fd << ":" << path << ' ';
506*795d594fSAndroid Build Coastguard Worker   }
507*795d594fSAndroid Build Coastguard Worker   return os;
508*795d594fSAndroid Build Coastguard Worker }
509*795d594fSAndroid Build Coastguard Worker 
510*795d594fSAndroid Build Coastguard Worker }  // namespace
511*795d594fSAndroid Build Coastguard Worker 
512*795d594fSAndroid Build Coastguard Worker #define RETURN_FATAL_IF_PRE_REBOOT(options)                                 \
513*795d594fSAndroid Build Coastguard Worker   if ((options).is_pre_reboot) {                                            \
514*795d594fSAndroid Build Coastguard Worker     return Fatal("This method is not supported in Pre-reboot Dexopt mode"); \
515*795d594fSAndroid Build Coastguard Worker   }
516*795d594fSAndroid Build Coastguard Worker 
517*795d594fSAndroid Build Coastguard Worker #define RETURN_FATAL_IF_NOT_PRE_REBOOT(options)                              \
518*795d594fSAndroid Build Coastguard Worker   if (!(options).is_pre_reboot) {                                            \
519*795d594fSAndroid Build Coastguard Worker     return Fatal("This method is only supported in Pre-reboot Dexopt mode"); \
520*795d594fSAndroid Build Coastguard Worker   }
521*795d594fSAndroid Build Coastguard Worker 
522*795d594fSAndroid Build Coastguard Worker #define RETURN_FATAL_IF_ARG_IS_PRE_REBOOT_IMPL(expected, arg, log_name)                        \
523*795d594fSAndroid Build Coastguard Worker   {                                                                                            \
524*795d594fSAndroid Build Coastguard Worker     auto&& __return_fatal_tmp = PreRebootFlag(arg);                                            \
525*795d594fSAndroid Build Coastguard Worker     if ((expected) != __return_fatal_tmp) {                                                    \
526*795d594fSAndroid Build Coastguard Worker       return Fatal(ART_FORMAT("Expected flag 'isPreReboot' in argument '{}' to be {}, got {}", \
527*795d594fSAndroid Build Coastguard Worker                               log_name,                                                        \
528*795d594fSAndroid Build Coastguard Worker                               expected,                                                        \
529*795d594fSAndroid Build Coastguard Worker                               __return_fatal_tmp));                                            \
530*795d594fSAndroid Build Coastguard Worker     }                                                                                          \
531*795d594fSAndroid Build Coastguard Worker   }
532*795d594fSAndroid Build Coastguard Worker 
533*795d594fSAndroid Build Coastguard Worker #define RETURN_FATAL_IF_PRE_REBOOT_MISMATCH(options, arg, log_name) \
534*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_ARG_IS_PRE_REBOOT_IMPL((options).is_pre_reboot, arg, log_name)
535*795d594fSAndroid Build Coastguard Worker 
536*795d594fSAndroid Build Coastguard Worker #define RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(arg, log_name) \
537*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_ARG_IS_PRE_REBOOT_IMPL(false, arg, log_name)
538*795d594fSAndroid Build Coastguard Worker 
Restorecon(const std::string & path,const std::optional<OutputArtifacts::PermissionSettings::SeContext> & se_context,bool recurse)539*795d594fSAndroid Build Coastguard Worker Result<void> Restorecon(
540*795d594fSAndroid Build Coastguard Worker     const std::string& path,
541*795d594fSAndroid Build Coastguard Worker     const std::optional<OutputArtifacts::PermissionSettings::SeContext>& se_context,
542*795d594fSAndroid Build Coastguard Worker     bool recurse) {
543*795d594fSAndroid Build Coastguard Worker   if (!kIsTargetAndroid) {
544*795d594fSAndroid Build Coastguard Worker     return {};
545*795d594fSAndroid Build Coastguard Worker   }
546*795d594fSAndroid Build Coastguard Worker 
547*795d594fSAndroid Build Coastguard Worker   unsigned int flags = recurse ? SELINUX_ANDROID_RESTORECON_RECURSE : 0;
548*795d594fSAndroid Build Coastguard Worker   int res = 0;
549*795d594fSAndroid Build Coastguard Worker   if (se_context.has_value()) {
550*795d594fSAndroid Build Coastguard Worker     res = selinux_android_restorecon_pkgdir(
551*795d594fSAndroid Build Coastguard Worker         path.c_str(), se_context->seInfo.c_str(), se_context->uid, flags);
552*795d594fSAndroid Build Coastguard Worker   } else {
553*795d594fSAndroid Build Coastguard Worker     res = selinux_android_restorecon(path.c_str(), flags);
554*795d594fSAndroid Build Coastguard Worker   }
555*795d594fSAndroid Build Coastguard Worker   if (res != 0) {
556*795d594fSAndroid Build Coastguard Worker     return ErrnoErrorf("Failed to restorecon directory '{}'", path);
557*795d594fSAndroid Build Coastguard Worker   }
558*795d594fSAndroid Build Coastguard Worker   return {};
559*795d594fSAndroid Build Coastguard Worker }
560*795d594fSAndroid Build Coastguard Worker 
isAlive(bool * _aidl_return)561*795d594fSAndroid Build Coastguard Worker ScopedAStatus Artd::isAlive(bool* _aidl_return) {
562*795d594fSAndroid Build Coastguard Worker   *_aidl_return = true;
563*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
564*795d594fSAndroid Build Coastguard Worker }
565*795d594fSAndroid Build Coastguard Worker 
deleteArtifacts(const ArtifactsPath & in_artifactsPath,int64_t * _aidl_return)566*795d594fSAndroid Build Coastguard Worker ScopedAStatus Artd::deleteArtifacts(const ArtifactsPath& in_artifactsPath, int64_t* _aidl_return) {
567*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_PRE_REBOOT(options_);
568*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(in_artifactsPath, "artifactsPath");
569*795d594fSAndroid Build Coastguard Worker 
570*795d594fSAndroid Build Coastguard Worker   RawArtifactsPath path = OR_RETURN_FATAL(BuildArtifactsPath(in_artifactsPath));
571*795d594fSAndroid Build Coastguard Worker 
572*795d594fSAndroid Build Coastguard Worker   *_aidl_return = 0;
573*795d594fSAndroid Build Coastguard Worker   *_aidl_return += GetSizeAndDeleteFile(path.oat_path);
574*795d594fSAndroid Build Coastguard Worker   *_aidl_return += GetSizeAndDeleteFile(path.vdex_path);
575*795d594fSAndroid Build Coastguard Worker   *_aidl_return += GetSizeAndDeleteFile(path.art_path);
576*795d594fSAndroid Build Coastguard Worker 
577*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
578*795d594fSAndroid Build Coastguard Worker }
579*795d594fSAndroid Build Coastguard Worker 
getDexoptStatus(const std::string & in_dexFile,const std::string & in_instructionSet,const std::optional<std::string> & in_classLoaderContext,GetDexoptStatusResult * _aidl_return)580*795d594fSAndroid Build Coastguard Worker ScopedAStatus Artd::getDexoptStatus(const std::string& in_dexFile,
581*795d594fSAndroid Build Coastguard Worker                                     const std::string& in_instructionSet,
582*795d594fSAndroid Build Coastguard Worker                                     const std::optional<std::string>& in_classLoaderContext,
583*795d594fSAndroid Build Coastguard Worker                                     GetDexoptStatusResult* _aidl_return) {
584*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_PRE_REBOOT(options_);
585*795d594fSAndroid Build Coastguard Worker 
586*795d594fSAndroid Build Coastguard Worker   Result<OatFileAssistantContext*> ofa_context = GetOatFileAssistantContext();
587*795d594fSAndroid Build Coastguard Worker   if (!ofa_context.ok()) {
588*795d594fSAndroid Build Coastguard Worker     return NonFatal("Failed to get runtime options: " + ofa_context.error().message());
589*795d594fSAndroid Build Coastguard Worker   }
590*795d594fSAndroid Build Coastguard Worker 
591*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<ClassLoaderContext> context;
592*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
593*795d594fSAndroid Build Coastguard Worker   auto oat_file_assistant = OatFileAssistant::Create(in_dexFile,
594*795d594fSAndroid Build Coastguard Worker                                                      in_instructionSet,
595*795d594fSAndroid Build Coastguard Worker                                                      in_classLoaderContext,
596*795d594fSAndroid Build Coastguard Worker                                                      /*load_executable=*/false,
597*795d594fSAndroid Build Coastguard Worker                                                      /*only_load_trusted_executable=*/true,
598*795d594fSAndroid Build Coastguard Worker                                                      ofa_context.value(),
599*795d594fSAndroid Build Coastguard Worker                                                      &context,
600*795d594fSAndroid Build Coastguard Worker                                                      &error_msg);
601*795d594fSAndroid Build Coastguard Worker   if (oat_file_assistant == nullptr) {
602*795d594fSAndroid Build Coastguard Worker     return NonFatal("Failed to create OatFileAssistant: " + error_msg);
603*795d594fSAndroid Build Coastguard Worker   }
604*795d594fSAndroid Build Coastguard Worker 
605*795d594fSAndroid Build Coastguard Worker   std::string ignored_odex_status;
606*795d594fSAndroid Build Coastguard Worker   OatFileAssistant::Location location;
607*795d594fSAndroid Build Coastguard Worker   oat_file_assistant->GetOptimizationStatus(&_aidl_return->locationDebugString,
608*795d594fSAndroid Build Coastguard Worker                                             &_aidl_return->compilerFilter,
609*795d594fSAndroid Build Coastguard Worker                                             &_aidl_return->compilationReason,
610*795d594fSAndroid Build Coastguard Worker                                             &ignored_odex_status,
611*795d594fSAndroid Build Coastguard Worker                                             &location);
612*795d594fSAndroid Build Coastguard Worker   _aidl_return->artifactsLocation = ArtifactsLocationToAidl(location);
613*795d594fSAndroid Build Coastguard Worker 
614*795d594fSAndroid Build Coastguard Worker   // We ignore odex_status because it is not meaningful. It can only be either "up-to-date",
615*795d594fSAndroid Build Coastguard Worker   // "apk-more-recent", or "io-error-no-oat", which means it doesn't give us information in addition
616*795d594fSAndroid Build Coastguard Worker   // to what we can learn from compiler_filter because compiler_filter will be the actual compiler
617*795d594fSAndroid Build Coastguard Worker   // filter, "run-from-apk-fallback", and "run-from-apk" in those three cases respectively.
618*795d594fSAndroid Build Coastguard Worker   DCHECK(ignored_odex_status == "up-to-date" || ignored_odex_status == "apk-more-recent" ||
619*795d594fSAndroid Build Coastguard Worker          ignored_odex_status == "io-error-no-oat");
620*795d594fSAndroid Build Coastguard Worker 
621*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
622*795d594fSAndroid Build Coastguard Worker }
623*795d594fSAndroid Build Coastguard Worker 
isProfileUsable(const ProfilePath & in_profile,const std::string & in_dexFile,bool * _aidl_return)624*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus Artd::isProfileUsable(const ProfilePath& in_profile,
625*795d594fSAndroid Build Coastguard Worker                                          const std::string& in_dexFile,
626*795d594fSAndroid Build Coastguard Worker                                          bool* _aidl_return) {
627*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(in_profile, "profile");
628*795d594fSAndroid Build Coastguard Worker 
629*795d594fSAndroid Build Coastguard Worker   std::string profile_path = OR_RETURN_FATAL(BuildProfileOrDmPath(in_profile));
630*795d594fSAndroid Build Coastguard Worker   OR_RETURN_FATAL(ValidateDexPath(in_dexFile));
631*795d594fSAndroid Build Coastguard Worker 
632*795d594fSAndroid Build Coastguard Worker   FdLogger fd_logger;
633*795d594fSAndroid Build Coastguard Worker 
634*795d594fSAndroid Build Coastguard Worker   CmdlineBuilder art_exec_args = OR_RETURN_FATAL(GetArtExecCmdlineBuilder());
635*795d594fSAndroid Build Coastguard Worker 
636*795d594fSAndroid Build Coastguard Worker   CmdlineBuilder args;
637*795d594fSAndroid Build Coastguard Worker   args.Add(OR_RETURN_FATAL(GetProfman()));
638*795d594fSAndroid Build Coastguard Worker 
639*795d594fSAndroid Build Coastguard Worker   Result<std::unique_ptr<File>> profile = OpenFileForReading(profile_path);
640*795d594fSAndroid Build Coastguard Worker   if (!profile.ok()) {
641*795d594fSAndroid Build Coastguard Worker     if (profile.error().code() == ENOENT) {
642*795d594fSAndroid Build Coastguard Worker       *_aidl_return = false;
643*795d594fSAndroid Build Coastguard Worker       return ScopedAStatus::ok();
644*795d594fSAndroid Build Coastguard Worker     }
645*795d594fSAndroid Build Coastguard Worker     return NonFatal(
646*795d594fSAndroid Build Coastguard Worker         ART_FORMAT("Failed to open profile '{}': {}", profile_path, profile.error().message()));
647*795d594fSAndroid Build Coastguard Worker   }
648*795d594fSAndroid Build Coastguard Worker   args.Add("--reference-profile-file-fd=%d", profile.value()->Fd());
649*795d594fSAndroid Build Coastguard Worker   fd_logger.Add(*profile.value());
650*795d594fSAndroid Build Coastguard Worker 
651*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<File> dex_file = OR_RETURN_NON_FATAL(OpenFileForReading(in_dexFile));
652*795d594fSAndroid Build Coastguard Worker   args.Add("--apk-fd=%d", dex_file->Fd());
653*795d594fSAndroid Build Coastguard Worker   fd_logger.Add(*dex_file);
654*795d594fSAndroid Build Coastguard Worker 
655*795d594fSAndroid Build Coastguard Worker   art_exec_args.Add("--keep-fds=%s", fd_logger.GetFds()).Add("--").Concat(std::move(args));
656*795d594fSAndroid Build Coastguard Worker 
657*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << "Running profman: " << Join(art_exec_args.Get(), /*separator=*/" ")
658*795d594fSAndroid Build Coastguard Worker             << "\nOpened FDs: " << fd_logger;
659*795d594fSAndroid Build Coastguard Worker 
660*795d594fSAndroid Build Coastguard Worker   Result<int> result = ExecAndReturnCode(art_exec_args.Get(), kShortTimeoutSec);
661*795d594fSAndroid Build Coastguard Worker   if (!result.ok()) {
662*795d594fSAndroid Build Coastguard Worker     return NonFatal("Failed to run profman: " + result.error().message());
663*795d594fSAndroid Build Coastguard Worker   }
664*795d594fSAndroid Build Coastguard Worker 
665*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << ART_FORMAT("profman returned code {}", result.value());
666*795d594fSAndroid Build Coastguard Worker 
667*795d594fSAndroid Build Coastguard Worker   if (result.value() != ProfmanResult::kSkipCompilationSmallDelta &&
668*795d594fSAndroid Build Coastguard Worker       result.value() != ProfmanResult::kSkipCompilationEmptyProfiles) {
669*795d594fSAndroid Build Coastguard Worker     return NonFatal(ART_FORMAT("profman returned an unexpected code: {}", result.value()));
670*795d594fSAndroid Build Coastguard Worker   }
671*795d594fSAndroid Build Coastguard Worker 
672*795d594fSAndroid Build Coastguard Worker   *_aidl_return = result.value() == ProfmanResult::kSkipCompilationSmallDelta;
673*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
674*795d594fSAndroid Build Coastguard Worker }
675*795d594fSAndroid Build Coastguard Worker 
CopyAndRewriteProfileImpl(File src,OutputProfile * dst_aidl,const std::string & dex_path,CopyAndRewriteProfileResult * aidl_return)676*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus Artd::CopyAndRewriteProfileImpl(File src,
677*795d594fSAndroid Build Coastguard Worker                                                    OutputProfile* dst_aidl,
678*795d594fSAndroid Build Coastguard Worker                                                    const std::string& dex_path,
679*795d594fSAndroid Build Coastguard Worker                                                    CopyAndRewriteProfileResult* aidl_return) {
680*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_PRE_REBOOT_MISMATCH(options_, *dst_aidl, "dst");
681*795d594fSAndroid Build Coastguard Worker   std::string dst_path = OR_RETURN_FATAL(BuildFinalProfilePath(dst_aidl->profilePath));
682*795d594fSAndroid Build Coastguard Worker   OR_RETURN_FATAL(ValidateDexPath(dex_path));
683*795d594fSAndroid Build Coastguard Worker 
684*795d594fSAndroid Build Coastguard Worker   FdLogger fd_logger;
685*795d594fSAndroid Build Coastguard Worker 
686*795d594fSAndroid Build Coastguard Worker   CmdlineBuilder art_exec_args = OR_RETURN_FATAL(GetArtExecCmdlineBuilder());
687*795d594fSAndroid Build Coastguard Worker 
688*795d594fSAndroid Build Coastguard Worker   CmdlineBuilder args;
689*795d594fSAndroid Build Coastguard Worker   args.Add(OR_RETURN_FATAL(GetProfman())).Add("--copy-and-update-profile-key");
690*795d594fSAndroid Build Coastguard Worker 
691*795d594fSAndroid Build Coastguard Worker   args.Add("--profile-file-fd=%d", src.Fd());
692*795d594fSAndroid Build Coastguard Worker   fd_logger.Add(src);
693*795d594fSAndroid Build Coastguard Worker 
694*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<File> dex_file = OR_RETURN_NON_FATAL(OpenFileForReading(dex_path));
695*795d594fSAndroid Build Coastguard Worker   args.Add("--apk-fd=%d", dex_file->Fd());
696*795d594fSAndroid Build Coastguard Worker   fd_logger.Add(*dex_file);
697*795d594fSAndroid Build Coastguard Worker 
698*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<NewFile> dst =
699*795d594fSAndroid Build Coastguard Worker       OR_RETURN_NON_FATAL(NewFile::Create(dst_path, dst_aidl->fsPermission));
700*795d594fSAndroid Build Coastguard Worker   args.Add("--reference-profile-file-fd=%d", dst->Fd());
701*795d594fSAndroid Build Coastguard Worker   fd_logger.Add(*dst);
702*795d594fSAndroid Build Coastguard Worker 
703*795d594fSAndroid Build Coastguard Worker   art_exec_args.Add("--keep-fds=%s", fd_logger.GetFds()).Add("--").Concat(std::move(args));
704*795d594fSAndroid Build Coastguard Worker 
705*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << "Running profman: " << Join(art_exec_args.Get(), /*separator=*/" ")
706*795d594fSAndroid Build Coastguard Worker             << "\nOpened FDs: " << fd_logger;
707*795d594fSAndroid Build Coastguard Worker 
708*795d594fSAndroid Build Coastguard Worker   Result<int> result = ExecAndReturnCode(art_exec_args.Get(), kShortTimeoutSec);
709*795d594fSAndroid Build Coastguard Worker   if (!result.ok()) {
710*795d594fSAndroid Build Coastguard Worker     return NonFatal("Failed to run profman: " + result.error().message());
711*795d594fSAndroid Build Coastguard Worker   }
712*795d594fSAndroid Build Coastguard Worker 
713*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << ART_FORMAT("profman returned code {}", result.value());
714*795d594fSAndroid Build Coastguard Worker 
715*795d594fSAndroid Build Coastguard Worker   if (result.value() == ProfmanResult::kCopyAndUpdateNoMatch ||
716*795d594fSAndroid Build Coastguard Worker       result.value() == ProfmanResult::kCopyAndUpdateErrorFailedToLoadProfile) {
717*795d594fSAndroid Build Coastguard Worker     *aidl_return = AnalyzeCopyAndRewriteProfileFailure(
718*795d594fSAndroid Build Coastguard Worker         &src, static_cast<ProfmanResult::CopyAndUpdateResult>(result.value()));
719*795d594fSAndroid Build Coastguard Worker     return ScopedAStatus::ok();
720*795d594fSAndroid Build Coastguard Worker   }
721*795d594fSAndroid Build Coastguard Worker 
722*795d594fSAndroid Build Coastguard Worker   if (result.value() != ProfmanResult::kCopyAndUpdateSuccess) {
723*795d594fSAndroid Build Coastguard Worker     return NonFatal(ART_FORMAT("profman returned an unexpected code: {}", result.value()));
724*795d594fSAndroid Build Coastguard Worker   }
725*795d594fSAndroid Build Coastguard Worker 
726*795d594fSAndroid Build Coastguard Worker   OR_RETURN_NON_FATAL(dst->Keep());
727*795d594fSAndroid Build Coastguard Worker   aidl_return->status = CopyAndRewriteProfileResult::Status::SUCCESS;
728*795d594fSAndroid Build Coastguard Worker   dst_aidl->profilePath.id = dst->TempId();
729*795d594fSAndroid Build Coastguard Worker   dst_aidl->profilePath.tmpPath = dst->TempPath();
730*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
731*795d594fSAndroid Build Coastguard Worker }
732*795d594fSAndroid Build Coastguard Worker 
copyAndRewriteProfile(const ProfilePath & in_src,OutputProfile * in_dst,const std::string & in_dexFile,CopyAndRewriteProfileResult * _aidl_return)733*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus Artd::copyAndRewriteProfile(const ProfilePath& in_src,
734*795d594fSAndroid Build Coastguard Worker                                                OutputProfile* in_dst,
735*795d594fSAndroid Build Coastguard Worker                                                const std::string& in_dexFile,
736*795d594fSAndroid Build Coastguard Worker                                                CopyAndRewriteProfileResult* _aidl_return) {
737*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(in_src, "src");
738*795d594fSAndroid Build Coastguard Worker 
739*795d594fSAndroid Build Coastguard Worker   std::string src_path = OR_RETURN_FATAL(BuildProfileOrDmPath(in_src));
740*795d594fSAndroid Build Coastguard Worker 
741*795d594fSAndroid Build Coastguard Worker   Result<std::unique_ptr<File>> src = OpenFileForReading(src_path);
742*795d594fSAndroid Build Coastguard Worker   if (!src.ok()) {
743*795d594fSAndroid Build Coastguard Worker     if (src.error().code() == ENOENT) {
744*795d594fSAndroid Build Coastguard Worker       _aidl_return->status = CopyAndRewriteProfileResult::Status::NO_PROFILE;
745*795d594fSAndroid Build Coastguard Worker       return ScopedAStatus::ok();
746*795d594fSAndroid Build Coastguard Worker     }
747*795d594fSAndroid Build Coastguard Worker     return NonFatal(
748*795d594fSAndroid Build Coastguard Worker         ART_FORMAT("Failed to open src profile '{}': {}", src_path, src.error().message()));
749*795d594fSAndroid Build Coastguard Worker   }
750*795d594fSAndroid Build Coastguard Worker 
751*795d594fSAndroid Build Coastguard Worker   return CopyAndRewriteProfileImpl(std::move(*src.value()), in_dst, in_dexFile, _aidl_return);
752*795d594fSAndroid Build Coastguard Worker }
753*795d594fSAndroid Build Coastguard Worker 
copyAndRewriteEmbeddedProfile(OutputProfile * in_dst,const std::string & in_dexFile,CopyAndRewriteProfileResult * _aidl_return)754*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus Artd::copyAndRewriteEmbeddedProfile(OutputProfile* in_dst,
755*795d594fSAndroid Build Coastguard Worker                                                        const std::string& in_dexFile,
756*795d594fSAndroid Build Coastguard Worker                                                        CopyAndRewriteProfileResult* _aidl_return) {
757*795d594fSAndroid Build Coastguard Worker   OR_RETURN_FATAL(ValidateDexPath(in_dexFile));
758*795d594fSAndroid Build Coastguard Worker 
759*795d594fSAndroid Build Coastguard Worker   Result<File> src = ExtractEmbeddedProfileToFd(in_dexFile);
760*795d594fSAndroid Build Coastguard Worker   if (!src.ok()) {
761*795d594fSAndroid Build Coastguard Worker     return NonFatal(ART_FORMAT(
762*795d594fSAndroid Build Coastguard Worker         "Failed to extract profile from dex file '{}': {}", in_dexFile, src.error().message()));
763*795d594fSAndroid Build Coastguard Worker   }
764*795d594fSAndroid Build Coastguard Worker   if (!src->IsValid()) {
765*795d594fSAndroid Build Coastguard Worker     _aidl_return->status = CopyAndRewriteProfileResult::Status::NO_PROFILE;
766*795d594fSAndroid Build Coastguard Worker     return ScopedAStatus::ok();
767*795d594fSAndroid Build Coastguard Worker   }
768*795d594fSAndroid Build Coastguard Worker 
769*795d594fSAndroid Build Coastguard Worker   return CopyAndRewriteProfileImpl(std::move(src.value()), in_dst, in_dexFile, _aidl_return);
770*795d594fSAndroid Build Coastguard Worker }
771*795d594fSAndroid Build Coastguard Worker 
commitTmpProfile(const TmpProfilePath & in_profile)772*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus Artd::commitTmpProfile(const TmpProfilePath& in_profile) {
773*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_PRE_REBOOT_MISMATCH(options_, in_profile, "profile");
774*795d594fSAndroid Build Coastguard Worker   std::string tmp_profile_path = OR_RETURN_FATAL(BuildTmpProfilePath(in_profile));
775*795d594fSAndroid Build Coastguard Worker   std::string ref_profile_path = OR_RETURN_FATAL(BuildFinalProfilePath(in_profile));
776*795d594fSAndroid Build Coastguard Worker 
777*795d594fSAndroid Build Coastguard Worker   std::error_code ec;
778*795d594fSAndroid Build Coastguard Worker   std::filesystem::rename(tmp_profile_path, ref_profile_path, ec);
779*795d594fSAndroid Build Coastguard Worker   if (ec) {
780*795d594fSAndroid Build Coastguard Worker     return NonFatal(ART_FORMAT(
781*795d594fSAndroid Build Coastguard Worker         "Failed to move '{}' to '{}': {}", tmp_profile_path, ref_profile_path, ec.message()));
782*795d594fSAndroid Build Coastguard Worker   }
783*795d594fSAndroid Build Coastguard Worker 
784*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
785*795d594fSAndroid Build Coastguard Worker }
786*795d594fSAndroid Build Coastguard Worker 
deleteProfile(const ProfilePath & in_profile)787*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus Artd::deleteProfile(const ProfilePath& in_profile) {
788*795d594fSAndroid Build Coastguard Worker   // `in_profile` can be either a Pre-reboot path or an ordinary one.
789*795d594fSAndroid Build Coastguard Worker   std::string profile_path = OR_RETURN_FATAL(BuildProfileOrDmPath(in_profile));
790*795d594fSAndroid Build Coastguard Worker   DeleteFile(profile_path);
791*795d594fSAndroid Build Coastguard Worker 
792*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
793*795d594fSAndroid Build Coastguard Worker }
794*795d594fSAndroid Build Coastguard Worker 
getProfileVisibility(const ProfilePath & in_profile,FileVisibility * _aidl_return)795*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus Artd::getProfileVisibility(const ProfilePath& in_profile,
796*795d594fSAndroid Build Coastguard Worker                                               FileVisibility* _aidl_return) {
797*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(in_profile, "profile");
798*795d594fSAndroid Build Coastguard Worker   std::string profile_path = OR_RETURN_FATAL(BuildProfileOrDmPath(in_profile));
799*795d594fSAndroid Build Coastguard Worker   *_aidl_return = OR_RETURN_NON_FATAL(GetFileVisibility(profile_path));
800*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
801*795d594fSAndroid Build Coastguard Worker }
802*795d594fSAndroid Build Coastguard Worker 
getArtifactsVisibility(const ArtifactsPath & in_artifactsPath,FileVisibility * _aidl_return)803*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus Artd::getArtifactsVisibility(const ArtifactsPath& in_artifactsPath,
804*795d594fSAndroid Build Coastguard Worker                                                 FileVisibility* _aidl_return) {
805*795d594fSAndroid Build Coastguard Worker   // `in_artifactsPath` can be either a Pre-reboot path or an ordinary one.
806*795d594fSAndroid Build Coastguard Worker   std::string oat_path = OR_RETURN_FATAL(BuildArtifactsPath(in_artifactsPath)).oat_path;
807*795d594fSAndroid Build Coastguard Worker   *_aidl_return = OR_RETURN_NON_FATAL(GetFileVisibility(oat_path));
808*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
809*795d594fSAndroid Build Coastguard Worker }
810*795d594fSAndroid Build Coastguard Worker 
getDexFileVisibility(const std::string & in_dexFile,FileVisibility * _aidl_return)811*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus Artd::getDexFileVisibility(const std::string& in_dexFile,
812*795d594fSAndroid Build Coastguard Worker                                               FileVisibility* _aidl_return) {
813*795d594fSAndroid Build Coastguard Worker   OR_RETURN_FATAL(ValidateDexPath(in_dexFile));
814*795d594fSAndroid Build Coastguard Worker   *_aidl_return = OR_RETURN_NON_FATAL(GetFileVisibility(in_dexFile));
815*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
816*795d594fSAndroid Build Coastguard Worker }
817*795d594fSAndroid Build Coastguard Worker 
getDmFileVisibility(const DexMetadataPath & in_dmFile,FileVisibility * _aidl_return)818*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus Artd::getDmFileVisibility(const DexMetadataPath& in_dmFile,
819*795d594fSAndroid Build Coastguard Worker                                              FileVisibility* _aidl_return) {
820*795d594fSAndroid Build Coastguard Worker   std::string dm_path = OR_RETURN_FATAL(BuildDexMetadataPath(in_dmFile));
821*795d594fSAndroid Build Coastguard Worker   *_aidl_return = OR_RETURN_NON_FATAL(GetFileVisibility(dm_path));
822*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
823*795d594fSAndroid Build Coastguard Worker }
824*795d594fSAndroid Build Coastguard Worker 
mergeProfiles(const std::vector<ProfilePath> & in_profiles,const std::optional<ProfilePath> & in_referenceProfile,OutputProfile * in_outputProfile,const std::vector<std::string> & in_dexFiles,const MergeProfileOptions & in_options,bool * _aidl_return)825*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus Artd::mergeProfiles(const std::vector<ProfilePath>& in_profiles,
826*795d594fSAndroid Build Coastguard Worker                                        const std::optional<ProfilePath>& in_referenceProfile,
827*795d594fSAndroid Build Coastguard Worker                                        OutputProfile* in_outputProfile,
828*795d594fSAndroid Build Coastguard Worker                                        const std::vector<std::string>& in_dexFiles,
829*795d594fSAndroid Build Coastguard Worker                                        const MergeProfileOptions& in_options,
830*795d594fSAndroid Build Coastguard Worker                                        bool* _aidl_return) {
831*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> profile_paths;
832*795d594fSAndroid Build Coastguard Worker   for (const ProfilePath& profile : in_profiles) {
833*795d594fSAndroid Build Coastguard Worker     RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(profile, "profiles");
834*795d594fSAndroid Build Coastguard Worker     std::string profile_path = OR_RETURN_FATAL(BuildProfileOrDmPath(profile));
835*795d594fSAndroid Build Coastguard Worker     if (profile.getTag() == ProfilePath::dexMetadataPath) {
836*795d594fSAndroid Build Coastguard Worker       return Fatal(ART_FORMAT("Does not support DM file, got '{}'", profile_path));
837*795d594fSAndroid Build Coastguard Worker     }
838*795d594fSAndroid Build Coastguard Worker     profile_paths.push_back(std::move(profile_path));
839*795d594fSAndroid Build Coastguard Worker   }
840*795d594fSAndroid Build Coastguard Worker 
841*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_PRE_REBOOT_MISMATCH(options_, *in_outputProfile, "outputProfile");
842*795d594fSAndroid Build Coastguard Worker   std::string output_profile_path =
843*795d594fSAndroid Build Coastguard Worker       OR_RETURN_FATAL(BuildFinalProfilePath(in_outputProfile->profilePath));
844*795d594fSAndroid Build Coastguard Worker   for (const std::string& dex_file : in_dexFiles) {
845*795d594fSAndroid Build Coastguard Worker     OR_RETURN_FATAL(ValidateDexPath(dex_file));
846*795d594fSAndroid Build Coastguard Worker   }
847*795d594fSAndroid Build Coastguard Worker   if (in_options.forceMerge + in_options.dumpOnly + in_options.dumpClassesAndMethods > 1) {
848*795d594fSAndroid Build Coastguard Worker     return Fatal("Only one of 'forceMerge', 'dumpOnly', and 'dumpClassesAndMethods' can be set");
849*795d594fSAndroid Build Coastguard Worker   }
850*795d594fSAndroid Build Coastguard Worker 
851*795d594fSAndroid Build Coastguard Worker   FdLogger fd_logger;
852*795d594fSAndroid Build Coastguard Worker 
853*795d594fSAndroid Build Coastguard Worker   CmdlineBuilder art_exec_args = OR_RETURN_FATAL(GetArtExecCmdlineBuilder());
854*795d594fSAndroid Build Coastguard Worker 
855*795d594fSAndroid Build Coastguard Worker   CmdlineBuilder args;
856*795d594fSAndroid Build Coastguard Worker   args.Add(OR_RETURN_FATAL(GetProfman()));
857*795d594fSAndroid Build Coastguard Worker 
858*795d594fSAndroid Build Coastguard Worker   std::vector<std::unique_ptr<File>> profile_files;
859*795d594fSAndroid Build Coastguard Worker   for (const std::string& profile_path : profile_paths) {
860*795d594fSAndroid Build Coastguard Worker     Result<std::unique_ptr<File>> profile_file = OpenFileForReading(profile_path);
861*795d594fSAndroid Build Coastguard Worker     if (!profile_file.ok()) {
862*795d594fSAndroid Build Coastguard Worker       if (profile_file.error().code() == ENOENT) {
863*795d594fSAndroid Build Coastguard Worker         // Skip non-existing file.
864*795d594fSAndroid Build Coastguard Worker         continue;
865*795d594fSAndroid Build Coastguard Worker       }
866*795d594fSAndroid Build Coastguard Worker       return NonFatal(ART_FORMAT(
867*795d594fSAndroid Build Coastguard Worker           "Failed to open profile '{}': {}", profile_path, profile_file.error().message()));
868*795d594fSAndroid Build Coastguard Worker     }
869*795d594fSAndroid Build Coastguard Worker     args.Add("--profile-file-fd=%d", profile_file.value()->Fd());
870*795d594fSAndroid Build Coastguard Worker     fd_logger.Add(*profile_file.value());
871*795d594fSAndroid Build Coastguard Worker     profile_files.push_back(std::move(profile_file.value()));
872*795d594fSAndroid Build Coastguard Worker   }
873*795d594fSAndroid Build Coastguard Worker 
874*795d594fSAndroid Build Coastguard Worker   if (profile_files.empty()) {
875*795d594fSAndroid Build Coastguard Worker     LOG(INFO) << "Merge skipped because there are no existing profiles";
876*795d594fSAndroid Build Coastguard Worker     *_aidl_return = false;
877*795d594fSAndroid Build Coastguard Worker     return ScopedAStatus::ok();
878*795d594fSAndroid Build Coastguard Worker   }
879*795d594fSAndroid Build Coastguard Worker 
880*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<NewFile> output_profile_file =
881*795d594fSAndroid Build Coastguard Worker       OR_RETURN_NON_FATAL(NewFile::Create(output_profile_path, in_outputProfile->fsPermission));
882*795d594fSAndroid Build Coastguard Worker 
883*795d594fSAndroid Build Coastguard Worker   if (in_referenceProfile.has_value()) {
884*795d594fSAndroid Build Coastguard Worker     if (in_options.dumpOnly || in_options.dumpClassesAndMethods) {
885*795d594fSAndroid Build Coastguard Worker       return Fatal(
886*795d594fSAndroid Build Coastguard Worker           "Reference profile must not be set when 'dumpOnly' or 'dumpClassesAndMethods' is set");
887*795d594fSAndroid Build Coastguard Worker     }
888*795d594fSAndroid Build Coastguard Worker     // `in_referenceProfile` can be either a Pre-reboot profile or an ordinary one.
889*795d594fSAndroid Build Coastguard Worker     std::string reference_profile_path =
890*795d594fSAndroid Build Coastguard Worker         OR_RETURN_FATAL(BuildProfileOrDmPath(*in_referenceProfile));
891*795d594fSAndroid Build Coastguard Worker     if (in_referenceProfile->getTag() == ProfilePath::dexMetadataPath) {
892*795d594fSAndroid Build Coastguard Worker       return Fatal(ART_FORMAT("Does not support DM file, got '{}'", reference_profile_path));
893*795d594fSAndroid Build Coastguard Worker     }
894*795d594fSAndroid Build Coastguard Worker     OR_RETURN_NON_FATAL(CopyFile(reference_profile_path, *output_profile_file));
895*795d594fSAndroid Build Coastguard Worker   }
896*795d594fSAndroid Build Coastguard Worker 
897*795d594fSAndroid Build Coastguard Worker   if (in_options.dumpOnly || in_options.dumpClassesAndMethods) {
898*795d594fSAndroid Build Coastguard Worker     args.Add("--dump-output-to-fd=%d", output_profile_file->Fd());
899*795d594fSAndroid Build Coastguard Worker   } else {
900*795d594fSAndroid Build Coastguard Worker     // profman is ok with this being an empty file when in_referenceProfile isn't set.
901*795d594fSAndroid Build Coastguard Worker     args.Add("--reference-profile-file-fd=%d", output_profile_file->Fd());
902*795d594fSAndroid Build Coastguard Worker   }
903*795d594fSAndroid Build Coastguard Worker   fd_logger.Add(*output_profile_file);
904*795d594fSAndroid Build Coastguard Worker 
905*795d594fSAndroid Build Coastguard Worker   std::vector<std::unique_ptr<File>> dex_files;
906*795d594fSAndroid Build Coastguard Worker   for (const std::string& dex_path : in_dexFiles) {
907*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<File> dex_file = OR_RETURN_NON_FATAL(OpenFileForReading(dex_path));
908*795d594fSAndroid Build Coastguard Worker     args.Add("--apk-fd=%d", dex_file->Fd());
909*795d594fSAndroid Build Coastguard Worker     fd_logger.Add(*dex_file);
910*795d594fSAndroid Build Coastguard Worker     dex_files.push_back(std::move(dex_file));
911*795d594fSAndroid Build Coastguard Worker   }
912*795d594fSAndroid Build Coastguard Worker 
913*795d594fSAndroid Build Coastguard Worker   if (in_options.dumpOnly || in_options.dumpClassesAndMethods) {
914*795d594fSAndroid Build Coastguard Worker     args.Add(in_options.dumpOnly ? "--dump-only" : "--dump-classes-and-methods");
915*795d594fSAndroid Build Coastguard Worker   } else {
916*795d594fSAndroid Build Coastguard Worker     args.AddIfNonEmpty("--min-new-classes-percent-change=%s",
917*795d594fSAndroid Build Coastguard Worker                        props_->GetOrEmpty("dalvik.vm.bgdexopt.new-classes-percent"))
918*795d594fSAndroid Build Coastguard Worker         .AddIfNonEmpty("--min-new-methods-percent-change=%s",
919*795d594fSAndroid Build Coastguard Worker                        props_->GetOrEmpty("dalvik.vm.bgdexopt.new-methods-percent"))
920*795d594fSAndroid Build Coastguard Worker         .AddIf(in_options.forceMerge, "--force-merge-and-analyze")
921*795d594fSAndroid Build Coastguard Worker         .AddIf(in_options.forBootImage, "--boot-image-merge");
922*795d594fSAndroid Build Coastguard Worker   }
923*795d594fSAndroid Build Coastguard Worker 
924*795d594fSAndroid Build Coastguard Worker   art_exec_args.Add("--keep-fds=%s", fd_logger.GetFds()).Add("--").Concat(std::move(args));
925*795d594fSAndroid Build Coastguard Worker 
926*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << "Running profman: " << Join(art_exec_args.Get(), /*separator=*/" ")
927*795d594fSAndroid Build Coastguard Worker             << "\nOpened FDs: " << fd_logger;
928*795d594fSAndroid Build Coastguard Worker 
929*795d594fSAndroid Build Coastguard Worker   Result<int> result = ExecAndReturnCode(art_exec_args.Get(), kShortTimeoutSec);
930*795d594fSAndroid Build Coastguard Worker   if (!result.ok()) {
931*795d594fSAndroid Build Coastguard Worker     return NonFatal("Failed to run profman: " + result.error().message());
932*795d594fSAndroid Build Coastguard Worker   }
933*795d594fSAndroid Build Coastguard Worker 
934*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << ART_FORMAT("profman returned code {}", result.value());
935*795d594fSAndroid Build Coastguard Worker 
936*795d594fSAndroid Build Coastguard Worker   if (result.value() == ProfmanResult::kSkipCompilationSmallDelta ||
937*795d594fSAndroid Build Coastguard Worker       result.value() == ProfmanResult::kSkipCompilationEmptyProfiles) {
938*795d594fSAndroid Build Coastguard Worker     *_aidl_return = false;
939*795d594fSAndroid Build Coastguard Worker     return ScopedAStatus::ok();
940*795d594fSAndroid Build Coastguard Worker   }
941*795d594fSAndroid Build Coastguard Worker 
942*795d594fSAndroid Build Coastguard Worker   ProfmanResult::ProcessingResult expected_result =
943*795d594fSAndroid Build Coastguard Worker       (in_options.dumpOnly || in_options.dumpClassesAndMethods) ? ProfmanResult::kSuccess :
944*795d594fSAndroid Build Coastguard Worker                                                                   ProfmanResult::kCompile;
945*795d594fSAndroid Build Coastguard Worker   if (result.value() != expected_result) {
946*795d594fSAndroid Build Coastguard Worker     return NonFatal(ART_FORMAT("profman returned an unexpected code: {}", result.value()));
947*795d594fSAndroid Build Coastguard Worker   }
948*795d594fSAndroid Build Coastguard Worker 
949*795d594fSAndroid Build Coastguard Worker   OR_RETURN_NON_FATAL(output_profile_file->Keep());
950*795d594fSAndroid Build Coastguard Worker   *_aidl_return = true;
951*795d594fSAndroid Build Coastguard Worker   in_outputProfile->profilePath.id = output_profile_file->TempId();
952*795d594fSAndroid Build Coastguard Worker   in_outputProfile->profilePath.tmpPath = output_profile_file->TempPath();
953*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
954*795d594fSAndroid Build Coastguard Worker }
955*795d594fSAndroid Build Coastguard Worker 
getDexoptNeeded(const std::string & in_dexFile,const std::string & in_instructionSet,const std::optional<std::string> & in_classLoaderContext,const std::string & in_compilerFilter,int32_t in_dexoptTrigger,GetDexoptNeededResult * _aidl_return)956*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus Artd::getDexoptNeeded(const std::string& in_dexFile,
957*795d594fSAndroid Build Coastguard Worker                                          const std::string& in_instructionSet,
958*795d594fSAndroid Build Coastguard Worker                                          const std::optional<std::string>& in_classLoaderContext,
959*795d594fSAndroid Build Coastguard Worker                                          const std::string& in_compilerFilter,
960*795d594fSAndroid Build Coastguard Worker                                          int32_t in_dexoptTrigger,
961*795d594fSAndroid Build Coastguard Worker                                          GetDexoptNeededResult* _aidl_return) {
962*795d594fSAndroid Build Coastguard Worker   Result<OatFileAssistantContext*> ofa_context = GetOatFileAssistantContext();
963*795d594fSAndroid Build Coastguard Worker   if (!ofa_context.ok()) {
964*795d594fSAndroid Build Coastguard Worker     return NonFatal("Failed to get runtime options: " + ofa_context.error().message());
965*795d594fSAndroid Build Coastguard Worker   }
966*795d594fSAndroid Build Coastguard Worker 
967*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<ClassLoaderContext> context;
968*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
969*795d594fSAndroid Build Coastguard Worker   auto oat_file_assistant = OatFileAssistant::Create(in_dexFile,
970*795d594fSAndroid Build Coastguard Worker                                                      in_instructionSet,
971*795d594fSAndroid Build Coastguard Worker                                                      in_classLoaderContext,
972*795d594fSAndroid Build Coastguard Worker                                                      /*load_executable=*/false,
973*795d594fSAndroid Build Coastguard Worker                                                      /*only_load_trusted_executable=*/true,
974*795d594fSAndroid Build Coastguard Worker                                                      ofa_context.value(),
975*795d594fSAndroid Build Coastguard Worker                                                      &context,
976*795d594fSAndroid Build Coastguard Worker                                                      &error_msg);
977*795d594fSAndroid Build Coastguard Worker   if (oat_file_assistant == nullptr) {
978*795d594fSAndroid Build Coastguard Worker     return NonFatal("Failed to create OatFileAssistant: " + error_msg);
979*795d594fSAndroid Build Coastguard Worker   }
980*795d594fSAndroid Build Coastguard Worker 
981*795d594fSAndroid Build Coastguard Worker   OatFileAssistant::DexOptStatus status;
982*795d594fSAndroid Build Coastguard Worker   _aidl_return->isDexoptNeeded =
983*795d594fSAndroid Build Coastguard Worker       oat_file_assistant->GetDexOptNeeded(OR_RETURN_FATAL(ParseCompilerFilter(in_compilerFilter)),
984*795d594fSAndroid Build Coastguard Worker                                           DexOptTriggerFromAidl(in_dexoptTrigger),
985*795d594fSAndroid Build Coastguard Worker                                           &status);
986*795d594fSAndroid Build Coastguard Worker   _aidl_return->isVdexUsable = status.IsVdexUsable();
987*795d594fSAndroid Build Coastguard Worker   _aidl_return->artifactsLocation = ArtifactsLocationToAidl(status.GetLocation());
988*795d594fSAndroid Build Coastguard Worker 
989*795d594fSAndroid Build Coastguard Worker   std::optional<bool> has_dex_files = oat_file_assistant->HasDexFiles(&error_msg);
990*795d594fSAndroid Build Coastguard Worker   if (!has_dex_files.has_value()) {
991*795d594fSAndroid Build Coastguard Worker     return NonFatal("Failed to open dex file: " + error_msg);
992*795d594fSAndroid Build Coastguard Worker   }
993*795d594fSAndroid Build Coastguard Worker   _aidl_return->hasDexCode = *has_dex_files;
994*795d594fSAndroid Build Coastguard Worker 
995*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
996*795d594fSAndroid Build Coastguard Worker }
997*795d594fSAndroid Build Coastguard Worker 
dexopt(const OutputArtifacts & in_outputArtifacts,const std::string & in_dexFile,const std::string & in_instructionSet,const std::optional<std::string> & in_classLoaderContext,const std::string & in_compilerFilter,const std::optional<ProfilePath> & in_profile,const std::optional<VdexPath> & in_inputVdex,const std::optional<DexMetadataPath> & in_dmFile,PriorityClass in_priorityClass,const DexoptOptions & in_dexoptOptions,const std::shared_ptr<IArtdCancellationSignal> & in_cancellationSignal,ArtdDexoptResult * _aidl_return)998*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus Artd::dexopt(
999*795d594fSAndroid Build Coastguard Worker     const OutputArtifacts& in_outputArtifacts,
1000*795d594fSAndroid Build Coastguard Worker     const std::string& in_dexFile,
1001*795d594fSAndroid Build Coastguard Worker     const std::string& in_instructionSet,
1002*795d594fSAndroid Build Coastguard Worker     const std::optional<std::string>& in_classLoaderContext,
1003*795d594fSAndroid Build Coastguard Worker     const std::string& in_compilerFilter,
1004*795d594fSAndroid Build Coastguard Worker     const std::optional<ProfilePath>& in_profile,
1005*795d594fSAndroid Build Coastguard Worker     const std::optional<VdexPath>& in_inputVdex,
1006*795d594fSAndroid Build Coastguard Worker     const std::optional<DexMetadataPath>& in_dmFile,
1007*795d594fSAndroid Build Coastguard Worker     PriorityClass in_priorityClass,
1008*795d594fSAndroid Build Coastguard Worker     const DexoptOptions& in_dexoptOptions,
1009*795d594fSAndroid Build Coastguard Worker     const std::shared_ptr<IArtdCancellationSignal>& in_cancellationSignal,
1010*795d594fSAndroid Build Coastguard Worker     ArtdDexoptResult* _aidl_return) {
1011*795d594fSAndroid Build Coastguard Worker   _aidl_return->cancelled = false;
1012*795d594fSAndroid Build Coastguard Worker 
1013*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_PRE_REBOOT_MISMATCH(options_, in_outputArtifacts, "outputArtifacts");
1014*795d594fSAndroid Build Coastguard Worker   RawArtifactsPath artifacts_path =
1015*795d594fSAndroid Build Coastguard Worker       OR_RETURN_FATAL(BuildArtifactsPath(in_outputArtifacts.artifactsPath));
1016*795d594fSAndroid Build Coastguard Worker   OR_RETURN_FATAL(ValidateDexPath(in_dexFile));
1017*795d594fSAndroid Build Coastguard Worker   // `in_profile` can be either a Pre-reboot profile or an ordinary one.
1018*795d594fSAndroid Build Coastguard Worker   std::optional<std::string> profile_path =
1019*795d594fSAndroid Build Coastguard Worker       in_profile.has_value() ?
1020*795d594fSAndroid Build Coastguard Worker           std::make_optional(OR_RETURN_FATAL(BuildProfileOrDmPath(in_profile.value()))) :
1021*795d594fSAndroid Build Coastguard Worker           std::nullopt;
1022*795d594fSAndroid Build Coastguard Worker   ArtdCancellationSignal* cancellation_signal =
1023*795d594fSAndroid Build Coastguard Worker       OR_RETURN_FATAL(ToArtdCancellationSignal(in_cancellationSignal.get()));
1024*795d594fSAndroid Build Coastguard Worker 
1025*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<ClassLoaderContext> context = nullptr;
1026*795d594fSAndroid Build Coastguard Worker   if (in_classLoaderContext.has_value()) {
1027*795d594fSAndroid Build Coastguard Worker     context = ClassLoaderContext::Create(in_classLoaderContext.value());
1028*795d594fSAndroid Build Coastguard Worker     if (context == nullptr) {
1029*795d594fSAndroid Build Coastguard Worker       return Fatal(
1030*795d594fSAndroid Build Coastguard Worker           ART_FORMAT("Class loader context '{}' is invalid", in_classLoaderContext.value()));
1031*795d594fSAndroid Build Coastguard Worker     }
1032*795d594fSAndroid Build Coastguard Worker   }
1033*795d594fSAndroid Build Coastguard Worker 
1034*795d594fSAndroid Build Coastguard Worker   std::string oat_dir_path;  // For restorecon, can be empty if the artifacts are in dalvik-cache.
1035*795d594fSAndroid Build Coastguard Worker   OR_RETURN_NON_FATAL(PrepareArtifactsDirs(in_outputArtifacts, &oat_dir_path));
1036*795d594fSAndroid Build Coastguard Worker 
1037*795d594fSAndroid Build Coastguard Worker   // First-round restorecon. artd doesn't have the permission to create files with the
1038*795d594fSAndroid Build Coastguard Worker   // `apk_data_file` label, so we need to restorecon the "oat" directory first so that files will
1039*795d594fSAndroid Build Coastguard Worker   // inherit `dalvikcache_data_file` rather than `apk_data_file`.
1040*795d594fSAndroid Build Coastguard Worker   if (!in_outputArtifacts.artifactsPath.isInDalvikCache) {
1041*795d594fSAndroid Build Coastguard Worker     OR_RETURN_NON_FATAL(restorecon_(
1042*795d594fSAndroid Build Coastguard Worker         oat_dir_path, in_outputArtifacts.permissionSettings.seContext, /*recurse=*/true));
1043*795d594fSAndroid Build Coastguard Worker   }
1044*795d594fSAndroid Build Coastguard Worker 
1045*795d594fSAndroid Build Coastguard Worker   FdLogger fd_logger;
1046*795d594fSAndroid Build Coastguard Worker 
1047*795d594fSAndroid Build Coastguard Worker   CmdlineBuilder art_exec_args = OR_RETURN_FATAL(GetArtExecCmdlineBuilder());
1048*795d594fSAndroid Build Coastguard Worker 
1049*795d594fSAndroid Build Coastguard Worker   CmdlineBuilder args;
1050*795d594fSAndroid Build Coastguard Worker   args.Add(OR_RETURN_FATAL(GetDex2Oat()));
1051*795d594fSAndroid Build Coastguard Worker 
1052*795d594fSAndroid Build Coastguard Worker   const FsPermission& fs_permission = in_outputArtifacts.permissionSettings.fileFsPermission;
1053*795d594fSAndroid Build Coastguard Worker 
1054*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<File> dex_file = OR_RETURN_NON_FATAL(OpenFileForReading(in_dexFile));
1055*795d594fSAndroid Build Coastguard Worker   args.Add("--zip-fd=%d", dex_file->Fd()).Add("--zip-location=%s", in_dexFile);
1056*795d594fSAndroid Build Coastguard Worker   fd_logger.Add(*dex_file);
1057*795d594fSAndroid Build Coastguard Worker   struct stat dex_st = OR_RETURN_NON_FATAL(Fstat(*dex_file));
1058*795d594fSAndroid Build Coastguard Worker   if ((dex_st.st_mode & S_IROTH) == 0) {
1059*795d594fSAndroid Build Coastguard Worker     if (fs_permission.isOtherReadable) {
1060*795d594fSAndroid Build Coastguard Worker       return NonFatal(ART_FORMAT(
1061*795d594fSAndroid Build Coastguard Worker           "Outputs cannot be other-readable because the dex file '{}' is not other-readable",
1062*795d594fSAndroid Build Coastguard Worker           dex_file->GetPath()));
1063*795d594fSAndroid Build Coastguard Worker     }
1064*795d594fSAndroid Build Coastguard Worker     // Negative numbers mean no `chown`. 0 means root.
1065*795d594fSAndroid Build Coastguard Worker     // Note: this check is more strict than it needs to be. For example, it doesn't allow the
1066*795d594fSAndroid Build Coastguard Worker     // outputs to belong to a group that is a subset of the dex file's group. This is for
1067*795d594fSAndroid Build Coastguard Worker     // simplicity, and it's okay as we don't have to handle such complicated cases in practice.
1068*795d594fSAndroid Build Coastguard Worker     if ((fs_permission.uid > 0 && static_cast<uid_t>(fs_permission.uid) != dex_st.st_uid) ||
1069*795d594fSAndroid Build Coastguard Worker         (fs_permission.gid > 0 && static_cast<gid_t>(fs_permission.gid) != dex_st.st_uid &&
1070*795d594fSAndroid Build Coastguard Worker          static_cast<gid_t>(fs_permission.gid) != dex_st.st_gid)) {
1071*795d594fSAndroid Build Coastguard Worker       return NonFatal(ART_FORMAT(
1072*795d594fSAndroid Build Coastguard Worker           "Outputs' owner doesn't match the dex file '{}' (outputs: {}:{}, dex file: {}:{})",
1073*795d594fSAndroid Build Coastguard Worker           dex_file->GetPath(),
1074*795d594fSAndroid Build Coastguard Worker           fs_permission.uid,
1075*795d594fSAndroid Build Coastguard Worker           fs_permission.gid,
1076*795d594fSAndroid Build Coastguard Worker           dex_st.st_uid,
1077*795d594fSAndroid Build Coastguard Worker           dex_st.st_gid));
1078*795d594fSAndroid Build Coastguard Worker     }
1079*795d594fSAndroid Build Coastguard Worker   }
1080*795d594fSAndroid Build Coastguard Worker 
1081*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<NewFile> oat_file =
1082*795d594fSAndroid Build Coastguard Worker       OR_RETURN_NON_FATAL(NewFile::Create(artifacts_path.oat_path, fs_permission));
1083*795d594fSAndroid Build Coastguard Worker   args.Add("--oat-fd=%d", oat_file->Fd()).Add("--oat-location=%s", artifacts_path.oat_path);
1084*795d594fSAndroid Build Coastguard Worker   fd_logger.Add(*oat_file);
1085*795d594fSAndroid Build Coastguard Worker 
1086*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<NewFile> vdex_file =
1087*795d594fSAndroid Build Coastguard Worker       OR_RETURN_NON_FATAL(NewFile::Create(artifacts_path.vdex_path, fs_permission));
1088*795d594fSAndroid Build Coastguard Worker   args.Add("--output-vdex-fd=%d", vdex_file->Fd());
1089*795d594fSAndroid Build Coastguard Worker   fd_logger.Add(*vdex_file);
1090*795d594fSAndroid Build Coastguard Worker 
1091*795d594fSAndroid Build Coastguard Worker   std::vector<NewFile*> files_to_commit{oat_file.get(), vdex_file.get()};
1092*795d594fSAndroid Build Coastguard Worker   std::vector<std::string_view> files_to_delete;
1093*795d594fSAndroid Build Coastguard Worker 
1094*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<NewFile> art_file = nullptr;
1095*795d594fSAndroid Build Coastguard Worker   if (in_dexoptOptions.generateAppImage) {
1096*795d594fSAndroid Build Coastguard Worker     art_file = OR_RETURN_NON_FATAL(NewFile::Create(artifacts_path.art_path, fs_permission));
1097*795d594fSAndroid Build Coastguard Worker     args.Add("--app-image-fd=%d", art_file->Fd());
1098*795d594fSAndroid Build Coastguard Worker     args.AddIfNonEmpty("--image-format=%s", props_->GetOrEmpty("dalvik.vm.appimageformat"));
1099*795d594fSAndroid Build Coastguard Worker     fd_logger.Add(*art_file);
1100*795d594fSAndroid Build Coastguard Worker     files_to_commit.push_back(art_file.get());
1101*795d594fSAndroid Build Coastguard Worker   } else {
1102*795d594fSAndroid Build Coastguard Worker     files_to_delete.push_back(artifacts_path.art_path);
1103*795d594fSAndroid Build Coastguard Worker   }
1104*795d594fSAndroid Build Coastguard Worker 
1105*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<NewFile> swap_file = nullptr;
1106*795d594fSAndroid Build Coastguard Worker   if (ShouldCreateSwapFileForDexopt()) {
1107*795d594fSAndroid Build Coastguard Worker     std::string swap_file_path = ART_FORMAT("{}.swap", artifacts_path.oat_path);
1108*795d594fSAndroid Build Coastguard Worker     swap_file =
1109*795d594fSAndroid Build Coastguard Worker         OR_RETURN_NON_FATAL(NewFile::Create(swap_file_path, FsPermission{.uid = -1, .gid = -1}));
1110*795d594fSAndroid Build Coastguard Worker     args.Add("--swap-fd=%d", swap_file->Fd());
1111*795d594fSAndroid Build Coastguard Worker     fd_logger.Add(*swap_file);
1112*795d594fSAndroid Build Coastguard Worker   }
1113*795d594fSAndroid Build Coastguard Worker 
1114*795d594fSAndroid Build Coastguard Worker   std::vector<std::unique_ptr<File>> context_files;
1115*795d594fSAndroid Build Coastguard Worker   if (context != nullptr) {
1116*795d594fSAndroid Build Coastguard Worker     std::vector<std::string> flattened_context = context->FlattenDexPaths();
1117*795d594fSAndroid Build Coastguard Worker     std::string dex_dir = Dirname(in_dexFile);
1118*795d594fSAndroid Build Coastguard Worker     std::vector<int> context_fds;
1119*795d594fSAndroid Build Coastguard Worker     for (const std::string& context_element : flattened_context) {
1120*795d594fSAndroid Build Coastguard Worker       std::string context_path = std::filesystem::path(dex_dir).append(context_element);
1121*795d594fSAndroid Build Coastguard Worker       OR_RETURN_FATAL(ValidateDexPath(context_path));
1122*795d594fSAndroid Build Coastguard Worker       std::unique_ptr<File> context_file = OR_RETURN_NON_FATAL(OpenFileForReading(context_path));
1123*795d594fSAndroid Build Coastguard Worker       context_fds.push_back(context_file->Fd());
1124*795d594fSAndroid Build Coastguard Worker       fd_logger.Add(*context_file);
1125*795d594fSAndroid Build Coastguard Worker       context_files.push_back(std::move(context_file));
1126*795d594fSAndroid Build Coastguard Worker     }
1127*795d594fSAndroid Build Coastguard Worker     args.AddIfNonEmpty("--class-loader-context-fds=%s", Join(context_fds, /*separator=*/':'))
1128*795d594fSAndroid Build Coastguard Worker         .Add("--class-loader-context=%s", in_classLoaderContext.value())
1129*795d594fSAndroid Build Coastguard Worker         .Add("--classpath-dir=%s", dex_dir);
1130*795d594fSAndroid Build Coastguard Worker   }
1131*795d594fSAndroid Build Coastguard Worker 
1132*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<File> input_vdex_file = nullptr;
1133*795d594fSAndroid Build Coastguard Worker   if (in_inputVdex.has_value()) {
1134*795d594fSAndroid Build Coastguard Worker     RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(in_inputVdex.value(), "inputVdex");
1135*795d594fSAndroid Build Coastguard Worker     std::string input_vdex_path = OR_RETURN_FATAL(BuildVdexPath(in_inputVdex.value()));
1136*795d594fSAndroid Build Coastguard Worker     input_vdex_file = OR_RETURN_NON_FATAL(OpenFileForReading(input_vdex_path));
1137*795d594fSAndroid Build Coastguard Worker     args.Add("--input-vdex-fd=%d", input_vdex_file->Fd());
1138*795d594fSAndroid Build Coastguard Worker     fd_logger.Add(*input_vdex_file);
1139*795d594fSAndroid Build Coastguard Worker   }
1140*795d594fSAndroid Build Coastguard Worker 
1141*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<File> dm_file = nullptr;
1142*795d594fSAndroid Build Coastguard Worker   if (in_dmFile.has_value()) {
1143*795d594fSAndroid Build Coastguard Worker     std::string dm_path = OR_RETURN_FATAL(BuildDexMetadataPath(in_dmFile.value()));
1144*795d594fSAndroid Build Coastguard Worker     dm_file = OR_RETURN_NON_FATAL(OpenFileForReading(dm_path));
1145*795d594fSAndroid Build Coastguard Worker     args.Add("--dm-fd=%d", dm_file->Fd());
1146*795d594fSAndroid Build Coastguard Worker     fd_logger.Add(*dm_file);
1147*795d594fSAndroid Build Coastguard Worker   }
1148*795d594fSAndroid Build Coastguard Worker 
1149*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<File> profile_file = nullptr;
1150*795d594fSAndroid Build Coastguard Worker   if (profile_path.has_value()) {
1151*795d594fSAndroid Build Coastguard Worker     profile_file = OR_RETURN_NON_FATAL(OpenFileForReading(profile_path.value()));
1152*795d594fSAndroid Build Coastguard Worker     args.Add("--profile-file-fd=%d", profile_file->Fd());
1153*795d594fSAndroid Build Coastguard Worker     fd_logger.Add(*profile_file);
1154*795d594fSAndroid Build Coastguard Worker     struct stat profile_st = OR_RETURN_NON_FATAL(Fstat(*profile_file));
1155*795d594fSAndroid Build Coastguard Worker     if (fs_permission.isOtherReadable && (profile_st.st_mode & S_IROTH) == 0) {
1156*795d594fSAndroid Build Coastguard Worker       return NonFatal(ART_FORMAT(
1157*795d594fSAndroid Build Coastguard Worker           "Outputs cannot be other-readable because the profile '{}' is not other-readable",
1158*795d594fSAndroid Build Coastguard Worker           profile_file->GetPath()));
1159*795d594fSAndroid Build Coastguard Worker     }
1160*795d594fSAndroid Build Coastguard Worker     // TODO(b/260228411): Check uid and gid.
1161*795d594fSAndroid Build Coastguard Worker   }
1162*795d594fSAndroid Build Coastguard Worker 
1163*795d594fSAndroid Build Coastguard Worker   // Second-round restorecon. Restorecon recursively after the output files are created, so that the
1164*795d594fSAndroid Build Coastguard Worker   // SELinux context is applied to all of them. The SELinux context of a file is mostly inherited
1165*795d594fSAndroid Build Coastguard Worker   // from the parent directory upon creation, but the MLS label is not inherited, so we need to
1166*795d594fSAndroid Build Coastguard Worker   // restorecon every file so that they have the right MLS label. If the files are in dalvik-cache,
1167*795d594fSAndroid Build Coastguard Worker   // there's no need to restorecon because they inherits the SELinux context of the dalvik-cache
1168*795d594fSAndroid Build Coastguard Worker   // directory and they don't need to have MLS labels.
1169*795d594fSAndroid Build Coastguard Worker   if (!in_outputArtifacts.artifactsPath.isInDalvikCache) {
1170*795d594fSAndroid Build Coastguard Worker     OR_RETURN_NON_FATAL(restorecon_(
1171*795d594fSAndroid Build Coastguard Worker         oat_dir_path, in_outputArtifacts.permissionSettings.seContext, /*recurse=*/true));
1172*795d594fSAndroid Build Coastguard Worker   }
1173*795d594fSAndroid Build Coastguard Worker 
1174*795d594fSAndroid Build Coastguard Worker   AddBootImageFlags(args);
1175*795d594fSAndroid Build Coastguard Worker   AddCompilerConfigFlags(
1176*795d594fSAndroid Build Coastguard Worker       in_instructionSet, in_compilerFilter, in_priorityClass, in_dexoptOptions, args);
1177*795d594fSAndroid Build Coastguard Worker   AddPerfConfigFlags(in_priorityClass, art_exec_args, args);
1178*795d594fSAndroid Build Coastguard Worker 
1179*795d594fSAndroid Build Coastguard Worker   // For being surfaced in crash reports on crashes.
1180*795d594fSAndroid Build Coastguard Worker   args.Add("--comments=%s", in_dexoptOptions.comments);
1181*795d594fSAndroid Build Coastguard Worker 
1182*795d594fSAndroid Build Coastguard Worker   art_exec_args.Add("--keep-fds=%s", fd_logger.GetFds()).Add("--").Concat(std::move(args));
1183*795d594fSAndroid Build Coastguard Worker 
1184*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << "Running dex2oat: " << Join(art_exec_args.Get(), /*separator=*/" ")
1185*795d594fSAndroid Build Coastguard Worker             << "\nOpened FDs: " << fd_logger;
1186*795d594fSAndroid Build Coastguard Worker 
1187*795d594fSAndroid Build Coastguard Worker   ProcessStat stat;
1188*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
1189*795d594fSAndroid Build Coastguard Worker   ExecResult result = exec_utils_->ExecAndReturnResult(art_exec_args.Get(),
1190*795d594fSAndroid Build Coastguard Worker                                                        kLongTimeoutSec,
1191*795d594fSAndroid Build Coastguard Worker                                                        cancellation_signal->CreateExecCallbacks(),
1192*795d594fSAndroid Build Coastguard Worker                                                        /*new_process_group=*/true,
1193*795d594fSAndroid Build Coastguard Worker                                                        &stat,
1194*795d594fSAndroid Build Coastguard Worker                                                        &error_msg);
1195*795d594fSAndroid Build Coastguard Worker   _aidl_return->wallTimeMs = stat.wall_time_ms;
1196*795d594fSAndroid Build Coastguard Worker   _aidl_return->cpuTimeMs = stat.cpu_time_ms;
1197*795d594fSAndroid Build Coastguard Worker 
1198*795d594fSAndroid Build Coastguard Worker   auto result_info = ART_FORMAT("[status={},exit_code={},signal={}]",
1199*795d594fSAndroid Build Coastguard Worker                                 static_cast<int>(result.status),
1200*795d594fSAndroid Build Coastguard Worker                                 result.exit_code,
1201*795d594fSAndroid Build Coastguard Worker                                 result.signal);
1202*795d594fSAndroid Build Coastguard Worker   if (result.status != ExecResult::kExited) {
1203*795d594fSAndroid Build Coastguard Worker     if (cancellation_signal->IsCancelled()) {
1204*795d594fSAndroid Build Coastguard Worker       _aidl_return->cancelled = true;
1205*795d594fSAndroid Build Coastguard Worker       return ScopedAStatus::ok();
1206*795d594fSAndroid Build Coastguard Worker     }
1207*795d594fSAndroid Build Coastguard Worker     return NonFatal(ART_FORMAT("Failed to run dex2oat: {} {}", error_msg, result_info));
1208*795d594fSAndroid Build Coastguard Worker   }
1209*795d594fSAndroid Build Coastguard Worker 
1210*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << ART_FORMAT("dex2oat returned code {}", result.exit_code);
1211*795d594fSAndroid Build Coastguard Worker 
1212*795d594fSAndroid Build Coastguard Worker   if (result.exit_code != 0) {
1213*795d594fSAndroid Build Coastguard Worker     return NonFatal(
1214*795d594fSAndroid Build Coastguard Worker         ART_FORMAT("dex2oat returned an unexpected code: {} {}", result.exit_code, result_info));
1215*795d594fSAndroid Build Coastguard Worker   }
1216*795d594fSAndroid Build Coastguard Worker 
1217*795d594fSAndroid Build Coastguard Worker   int64_t size_bytes = 0;
1218*795d594fSAndroid Build Coastguard Worker   int64_t size_before_bytes = 0;
1219*795d594fSAndroid Build Coastguard Worker   for (const NewFile* file : files_to_commit) {
1220*795d594fSAndroid Build Coastguard Worker     size_bytes += GetSize(file->TempPath()).value_or(0);
1221*795d594fSAndroid Build Coastguard Worker     size_before_bytes += GetSize(file->FinalPath()).value_or(0);
1222*795d594fSAndroid Build Coastguard Worker   }
1223*795d594fSAndroid Build Coastguard Worker   for (std::string_view path : files_to_delete) {
1224*795d594fSAndroid Build Coastguard Worker     size_before_bytes += GetSize(path).value_or(0);
1225*795d594fSAndroid Build Coastguard Worker   }
1226*795d594fSAndroid Build Coastguard Worker   OR_RETURN_NON_FATAL(NewFile::CommitAllOrAbandon(files_to_commit, files_to_delete));
1227*795d594fSAndroid Build Coastguard Worker 
1228*795d594fSAndroid Build Coastguard Worker   _aidl_return->sizeBytes = size_bytes;
1229*795d594fSAndroid Build Coastguard Worker   _aidl_return->sizeBeforeBytes = size_before_bytes;
1230*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
1231*795d594fSAndroid Build Coastguard Worker }
1232*795d594fSAndroid Build Coastguard Worker 
cancel()1233*795d594fSAndroid Build Coastguard Worker ScopedAStatus ArtdCancellationSignal::cancel() {
1234*795d594fSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> lock(mu_);
1235*795d594fSAndroid Build Coastguard Worker   is_cancelled_ = true;
1236*795d594fSAndroid Build Coastguard Worker   for (pid_t pid : pids_) {
1237*795d594fSAndroid Build Coastguard Worker     // Kill the whole process group.
1238*795d594fSAndroid Build Coastguard Worker     int res = kill_(-pid, SIGKILL);
1239*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(res, 0);
1240*795d594fSAndroid Build Coastguard Worker   }
1241*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
1242*795d594fSAndroid Build Coastguard Worker }
1243*795d594fSAndroid Build Coastguard Worker 
getType(int64_t * _aidl_return)1244*795d594fSAndroid Build Coastguard Worker ScopedAStatus ArtdCancellationSignal::getType(int64_t* _aidl_return) {
1245*795d594fSAndroid Build Coastguard Worker   *_aidl_return = reinterpret_cast<intptr_t>(kArtdCancellationSignalType);
1246*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
1247*795d594fSAndroid Build Coastguard Worker }
1248*795d594fSAndroid Build Coastguard Worker 
CreateExecCallbacks()1249*795d594fSAndroid Build Coastguard Worker ExecCallbacks ArtdCancellationSignal::CreateExecCallbacks() {
1250*795d594fSAndroid Build Coastguard Worker   return {
1251*795d594fSAndroid Build Coastguard Worker       .on_start =
1252*795d594fSAndroid Build Coastguard Worker           [&](pid_t pid) {
1253*795d594fSAndroid Build Coastguard Worker             std::lock_guard<std::mutex> lock(mu_);
1254*795d594fSAndroid Build Coastguard Worker             pids_.insert(pid);
1255*795d594fSAndroid Build Coastguard Worker             // Handle cancellation signals sent before the process starts.
1256*795d594fSAndroid Build Coastguard Worker             if (is_cancelled_) {
1257*795d594fSAndroid Build Coastguard Worker               int res = kill_(-pid, SIGKILL);
1258*795d594fSAndroid Build Coastguard Worker               DCHECK_EQ(res, 0);
1259*795d594fSAndroid Build Coastguard Worker             }
1260*795d594fSAndroid Build Coastguard Worker           },
1261*795d594fSAndroid Build Coastguard Worker       .on_end =
1262*795d594fSAndroid Build Coastguard Worker           [&](pid_t pid) {
1263*795d594fSAndroid Build Coastguard Worker             std::lock_guard<std::mutex> lock(mu_);
1264*795d594fSAndroid Build Coastguard Worker             // The pid should no longer receive kill signals sent by `cancellation_signal`.
1265*795d594fSAndroid Build Coastguard Worker             pids_.erase(pid);
1266*795d594fSAndroid Build Coastguard Worker           },
1267*795d594fSAndroid Build Coastguard Worker   };
1268*795d594fSAndroid Build Coastguard Worker }
1269*795d594fSAndroid Build Coastguard Worker 
IsCancelled()1270*795d594fSAndroid Build Coastguard Worker bool ArtdCancellationSignal::IsCancelled() {
1271*795d594fSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> lock(mu_);
1272*795d594fSAndroid Build Coastguard Worker   return is_cancelled_;
1273*795d594fSAndroid Build Coastguard Worker }
1274*795d594fSAndroid Build Coastguard Worker 
createCancellationSignal(std::shared_ptr<IArtdCancellationSignal> * _aidl_return)1275*795d594fSAndroid Build Coastguard Worker ScopedAStatus Artd::createCancellationSignal(
1276*795d594fSAndroid Build Coastguard Worker     std::shared_ptr<IArtdCancellationSignal>* _aidl_return) {
1277*795d594fSAndroid Build Coastguard Worker   *_aidl_return = ndk::SharedRefBase::make<ArtdCancellationSignal>(kill_);
1278*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
1279*795d594fSAndroid Build Coastguard Worker }
1280*795d594fSAndroid Build Coastguard Worker 
cleanup(const std::vector<ProfilePath> & in_profilesToKeep,const std::vector<ArtifactsPath> & in_artifactsToKeep,const std::vector<VdexPath> & in_vdexFilesToKeep,const std::vector<RuntimeArtifactsPath> & in_runtimeArtifactsToKeep,bool in_keepPreRebootStagedFiles,int64_t * _aidl_return)1281*795d594fSAndroid Build Coastguard Worker ScopedAStatus Artd::cleanup(const std::vector<ProfilePath>& in_profilesToKeep,
1282*795d594fSAndroid Build Coastguard Worker                             const std::vector<ArtifactsPath>& in_artifactsToKeep,
1283*795d594fSAndroid Build Coastguard Worker                             const std::vector<VdexPath>& in_vdexFilesToKeep,
1284*795d594fSAndroid Build Coastguard Worker                             const std::vector<RuntimeArtifactsPath>& in_runtimeArtifactsToKeep,
1285*795d594fSAndroid Build Coastguard Worker                             bool in_keepPreRebootStagedFiles,
1286*795d594fSAndroid Build Coastguard Worker                             int64_t* _aidl_return) {
1287*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_PRE_REBOOT(options_);
1288*795d594fSAndroid Build Coastguard Worker   std::unordered_set<std::string> files_to_keep;
1289*795d594fSAndroid Build Coastguard Worker   for (const ProfilePath& profile : in_profilesToKeep) {
1290*795d594fSAndroid Build Coastguard Worker     RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(profile, "profilesToKeep");
1291*795d594fSAndroid Build Coastguard Worker     files_to_keep.insert(OR_RETURN_FATAL(BuildProfileOrDmPath(profile)));
1292*795d594fSAndroid Build Coastguard Worker   }
1293*795d594fSAndroid Build Coastguard Worker   for (const ArtifactsPath& artifacts : in_artifactsToKeep) {
1294*795d594fSAndroid Build Coastguard Worker     RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(artifacts, "artifactsToKeep");
1295*795d594fSAndroid Build Coastguard Worker     RawArtifactsPath path = OR_RETURN_FATAL(BuildArtifactsPath(artifacts));
1296*795d594fSAndroid Build Coastguard Worker     files_to_keep.insert(std::move(path.oat_path));
1297*795d594fSAndroid Build Coastguard Worker     files_to_keep.insert(std::move(path.vdex_path));
1298*795d594fSAndroid Build Coastguard Worker     files_to_keep.insert(std::move(path.art_path));
1299*795d594fSAndroid Build Coastguard Worker   }
1300*795d594fSAndroid Build Coastguard Worker   for (const VdexPath& vdex : in_vdexFilesToKeep) {
1301*795d594fSAndroid Build Coastguard Worker     RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(vdex, "vdexFilesToKeep");
1302*795d594fSAndroid Build Coastguard Worker     files_to_keep.insert(OR_RETURN_FATAL(BuildVdexPath(vdex)));
1303*795d594fSAndroid Build Coastguard Worker   }
1304*795d594fSAndroid Build Coastguard Worker   std::string android_data = OR_RETURN_NON_FATAL(GetAndroidDataOrError());
1305*795d594fSAndroid Build Coastguard Worker   std::string android_expand = OR_RETURN_NON_FATAL(GetAndroidExpandOrError());
1306*795d594fSAndroid Build Coastguard Worker   for (const RuntimeArtifactsPath& runtime_image_path : in_runtimeArtifactsToKeep) {
1307*795d594fSAndroid Build Coastguard Worker     OR_RETURN_FATAL(ValidateRuntimeArtifactsPath(runtime_image_path));
1308*795d594fSAndroid Build Coastguard Worker     std::vector<std::string> files =
1309*795d594fSAndroid Build Coastguard Worker         ListRuntimeArtifactsFiles(android_data, android_expand, runtime_image_path);
1310*795d594fSAndroid Build Coastguard Worker     std::move(files.begin(), files.end(), std::inserter(files_to_keep, files_to_keep.end()));
1311*795d594fSAndroid Build Coastguard Worker   }
1312*795d594fSAndroid Build Coastguard Worker   *_aidl_return = 0;
1313*795d594fSAndroid Build Coastguard Worker   for (const std::string& file : ListManagedFiles(android_data, android_expand)) {
1314*795d594fSAndroid Build Coastguard Worker     if (files_to_keep.find(file) == files_to_keep.end() &&
1315*795d594fSAndroid Build Coastguard Worker         (!in_keepPreRebootStagedFiles || !IsPreRebootStagedFile(file))) {
1316*795d594fSAndroid Build Coastguard Worker       LOG(INFO) << ART_FORMAT("Cleaning up obsolete file '{}'", file);
1317*795d594fSAndroid Build Coastguard Worker       *_aidl_return += GetSizeAndDeleteFile(file);
1318*795d594fSAndroid Build Coastguard Worker     }
1319*795d594fSAndroid Build Coastguard Worker   }
1320*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
1321*795d594fSAndroid Build Coastguard Worker }
1322*795d594fSAndroid Build Coastguard Worker 
cleanUpPreRebootStagedFiles()1323*795d594fSAndroid Build Coastguard Worker ScopedAStatus Artd::cleanUpPreRebootStagedFiles() {
1324*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_PRE_REBOOT(options_);
1325*795d594fSAndroid Build Coastguard Worker   std::string android_data = OR_RETURN_NON_FATAL(GetAndroidDataOrError());
1326*795d594fSAndroid Build Coastguard Worker   std::string android_expand = OR_RETURN_NON_FATAL(GetAndroidExpandOrError());
1327*795d594fSAndroid Build Coastguard Worker   for (const std::string& file : ListManagedFiles(android_data, android_expand)) {
1328*795d594fSAndroid Build Coastguard Worker     if (IsPreRebootStagedFile(file)) {
1329*795d594fSAndroid Build Coastguard Worker       LOG(INFO) << ART_FORMAT("Cleaning up obsolete Pre-reboot staged file '{}'", file);
1330*795d594fSAndroid Build Coastguard Worker       DeleteFile(file);
1331*795d594fSAndroid Build Coastguard Worker     }
1332*795d594fSAndroid Build Coastguard Worker   }
1333*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
1334*795d594fSAndroid Build Coastguard Worker }
1335*795d594fSAndroid Build Coastguard Worker 
isInDalvikCache(const std::string & in_dexFile,bool * _aidl_return)1336*795d594fSAndroid Build Coastguard Worker ScopedAStatus Artd::isInDalvikCache(const std::string& in_dexFile, bool* _aidl_return) {
1337*795d594fSAndroid Build Coastguard Worker   // The artifacts should be in the global dalvik-cache directory if:
1338*795d594fSAndroid Build Coastguard Worker   // (1). the dex file is on a system partition, even if the partition is remounted read-write,
1339*795d594fSAndroid Build Coastguard Worker   //      or
1340*795d594fSAndroid Build Coastguard Worker   // (2). the dex file is in any other readonly location. (At the time of writing, this only
1341*795d594fSAndroid Build Coastguard Worker   //      include Incremental FS.)
1342*795d594fSAndroid Build Coastguard Worker   //
1343*795d594fSAndroid Build Coastguard Worker   // We cannot rely on access(2) because:
1344*795d594fSAndroid Build Coastguard Worker   // - It doesn't take effective capabilities into account, from which artd gets root access
1345*795d594fSAndroid Build Coastguard Worker   //   to the filesystem.
1346*795d594fSAndroid Build Coastguard Worker   // - The `faccessat` variant with the `AT_EACCESS` flag, which takes effective capabilities
1347*795d594fSAndroid Build Coastguard Worker   //   into account, is not supported by bionic.
1348*795d594fSAndroid Build Coastguard Worker 
1349*795d594fSAndroid Build Coastguard Worker   OR_RETURN_FATAL(ValidateDexPath(in_dexFile));
1350*795d594fSAndroid Build Coastguard Worker 
1351*795d594fSAndroid Build Coastguard Worker   std::vector<FstabEntry> entries = OR_RETURN_NON_FATAL(GetProcMountsAncestorsOfPath(in_dexFile));
1352*795d594fSAndroid Build Coastguard Worker   // The last one controls because `/proc/mounts` reflects the sequence of `mount`.
1353*795d594fSAndroid Build Coastguard Worker   for (auto it = entries.rbegin(); it != entries.rend(); it++) {
1354*795d594fSAndroid Build Coastguard Worker     if (it->fs_type == "overlay") {
1355*795d594fSAndroid Build Coastguard Worker       // Ignore the overlays created by `remount`.
1356*795d594fSAndroid Build Coastguard Worker       continue;
1357*795d594fSAndroid Build Coastguard Worker     }
1358*795d594fSAndroid Build Coastguard Worker     // We need to special-case Incremental FS since it is tagged as read-write while it's actually
1359*795d594fSAndroid Build Coastguard Worker     // not.
1360*795d594fSAndroid Build Coastguard Worker     *_aidl_return = (it->flags & MS_RDONLY) != 0 || it->fs_type == "incremental-fs";
1361*795d594fSAndroid Build Coastguard Worker     return ScopedAStatus::ok();
1362*795d594fSAndroid Build Coastguard Worker   }
1363*795d594fSAndroid Build Coastguard Worker 
1364*795d594fSAndroid Build Coastguard Worker   return NonFatal(ART_FORMAT("Fstab entries not found for '{}'", in_dexFile));
1365*795d594fSAndroid Build Coastguard Worker }
1366*795d594fSAndroid Build Coastguard Worker 
deleteRuntimeArtifacts(const RuntimeArtifactsPath & in_runtimeArtifactsPath,int64_t * _aidl_return)1367*795d594fSAndroid Build Coastguard Worker ScopedAStatus Artd::deleteRuntimeArtifacts(const RuntimeArtifactsPath& in_runtimeArtifactsPath,
1368*795d594fSAndroid Build Coastguard Worker                                            int64_t* _aidl_return) {
1369*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_PRE_REBOOT(options_);
1370*795d594fSAndroid Build Coastguard Worker   OR_RETURN_FATAL(ValidateRuntimeArtifactsPath(in_runtimeArtifactsPath));
1371*795d594fSAndroid Build Coastguard Worker   *_aidl_return = 0;
1372*795d594fSAndroid Build Coastguard Worker   std::string android_data = OR_LOG_AND_RETURN_OK(GetAndroidDataOrError());
1373*795d594fSAndroid Build Coastguard Worker   std::string android_expand = OR_LOG_AND_RETURN_OK(GetAndroidExpandOrError());
1374*795d594fSAndroid Build Coastguard Worker   for (const std::string& file :
1375*795d594fSAndroid Build Coastguard Worker        ListRuntimeArtifactsFiles(android_data, android_expand, in_runtimeArtifactsPath)) {
1376*795d594fSAndroid Build Coastguard Worker     *_aidl_return += GetSizeAndDeleteFile(file);
1377*795d594fSAndroid Build Coastguard Worker   }
1378*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
1379*795d594fSAndroid Build Coastguard Worker }
1380*795d594fSAndroid Build Coastguard Worker 
getArtifactsSize(const ArtifactsPath & in_artifactsPath,int64_t * _aidl_return)1381*795d594fSAndroid Build Coastguard Worker ScopedAStatus Artd::getArtifactsSize(const ArtifactsPath& in_artifactsPath, int64_t* _aidl_return) {
1382*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_PRE_REBOOT(options_);
1383*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(in_artifactsPath, "artifactsPath");
1384*795d594fSAndroid Build Coastguard Worker   RawArtifactsPath path = OR_RETURN_FATAL(BuildArtifactsPath(in_artifactsPath));
1385*795d594fSAndroid Build Coastguard Worker   *_aidl_return = 0;
1386*795d594fSAndroid Build Coastguard Worker   *_aidl_return += GetSize(path.oat_path).value_or(0);
1387*795d594fSAndroid Build Coastguard Worker   *_aidl_return += GetSize(path.vdex_path).value_or(0);
1388*795d594fSAndroid Build Coastguard Worker   *_aidl_return += GetSize(path.art_path).value_or(0);
1389*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
1390*795d594fSAndroid Build Coastguard Worker }
1391*795d594fSAndroid Build Coastguard Worker 
getVdexFileSize(const VdexPath & in_vdexPath,int64_t * _aidl_return)1392*795d594fSAndroid Build Coastguard Worker ScopedAStatus Artd::getVdexFileSize(const VdexPath& in_vdexPath, int64_t* _aidl_return) {
1393*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_PRE_REBOOT(options_);
1394*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(in_vdexPath, "vdexPath");
1395*795d594fSAndroid Build Coastguard Worker   std::string vdex_path = OR_RETURN_FATAL(BuildVdexPath(in_vdexPath));
1396*795d594fSAndroid Build Coastguard Worker   *_aidl_return = GetSize(vdex_path).value_or(0);
1397*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
1398*795d594fSAndroid Build Coastguard Worker }
1399*795d594fSAndroid Build Coastguard Worker 
getRuntimeArtifactsSize(const RuntimeArtifactsPath & in_runtimeArtifactsPath,int64_t * _aidl_return)1400*795d594fSAndroid Build Coastguard Worker ScopedAStatus Artd::getRuntimeArtifactsSize(const RuntimeArtifactsPath& in_runtimeArtifactsPath,
1401*795d594fSAndroid Build Coastguard Worker                                             int64_t* _aidl_return) {
1402*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_PRE_REBOOT(options_);
1403*795d594fSAndroid Build Coastguard Worker   OR_RETURN_FATAL(ValidateRuntimeArtifactsPath(in_runtimeArtifactsPath));
1404*795d594fSAndroid Build Coastguard Worker   *_aidl_return = 0;
1405*795d594fSAndroid Build Coastguard Worker   std::string android_data = OR_LOG_AND_RETURN_OK(GetAndroidDataOrError());
1406*795d594fSAndroid Build Coastguard Worker   std::string android_expand = OR_LOG_AND_RETURN_OK(GetAndroidExpandOrError());
1407*795d594fSAndroid Build Coastguard Worker   for (const std::string& file :
1408*795d594fSAndroid Build Coastguard Worker        ListRuntimeArtifactsFiles(android_data, android_expand, in_runtimeArtifactsPath)) {
1409*795d594fSAndroid Build Coastguard Worker     *_aidl_return += GetSize(file).value_or(0);
1410*795d594fSAndroid Build Coastguard Worker   }
1411*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
1412*795d594fSAndroid Build Coastguard Worker }
1413*795d594fSAndroid Build Coastguard Worker 
getProfileSize(const ProfilePath & in_profile,int64_t * _aidl_return)1414*795d594fSAndroid Build Coastguard Worker ScopedAStatus Artd::getProfileSize(const ProfilePath& in_profile, int64_t* _aidl_return) {
1415*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_PRE_REBOOT(options_);
1416*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(in_profile, "profile");
1417*795d594fSAndroid Build Coastguard Worker   std::string profile_path = OR_RETURN_FATAL(BuildProfileOrDmPath(in_profile));
1418*795d594fSAndroid Build Coastguard Worker   *_aidl_return = GetSize(profile_path).value_or(0);
1419*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
1420*795d594fSAndroid Build Coastguard Worker }
1421*795d594fSAndroid Build Coastguard Worker 
initProfileSaveNotification(const PrimaryCurProfilePath & in_profilePath,int in_pid,std::shared_ptr<IArtdNotification> * _aidl_return)1422*795d594fSAndroid Build Coastguard Worker ScopedAStatus Artd::initProfileSaveNotification(const PrimaryCurProfilePath& in_profilePath,
1423*795d594fSAndroid Build Coastguard Worker                                                 int in_pid,
1424*795d594fSAndroid Build Coastguard Worker                                                 std::shared_ptr<IArtdNotification>* _aidl_return) {
1425*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_PRE_REBOOT(options_);
1426*795d594fSAndroid Build Coastguard Worker 
1427*795d594fSAndroid Build Coastguard Worker   std::string path = OR_RETURN_FATAL(BuildPrimaryCurProfilePath(in_profilePath));
1428*795d594fSAndroid Build Coastguard Worker 
1429*795d594fSAndroid Build Coastguard Worker   unique_fd inotify_fd(inotify_init1(IN_NONBLOCK | IN_CLOEXEC));
1430*795d594fSAndroid Build Coastguard Worker   if (inotify_fd < 0) {
1431*795d594fSAndroid Build Coastguard Worker     return NonFatal(ART_FORMAT("Failed to inotify_init1: {}", strerror(errno)));
1432*795d594fSAndroid Build Coastguard Worker   }
1433*795d594fSAndroid Build Coastguard Worker 
1434*795d594fSAndroid Build Coastguard Worker   // Watch the dir rather than the file itself because profiles are moved in rather than updated in
1435*795d594fSAndroid Build Coastguard Worker   // place.
1436*795d594fSAndroid Build Coastguard Worker   std::string dir = Dirname(path);
1437*795d594fSAndroid Build Coastguard Worker   int wd = inotify_add_watch(inotify_fd, dir.c_str(), IN_MOVED_TO);
1438*795d594fSAndroid Build Coastguard Worker   if (wd < 0) {
1439*795d594fSAndroid Build Coastguard Worker     return NonFatal(ART_FORMAT("Failed to inotify_add_watch '{}': {}", dir, strerror(errno)));
1440*795d594fSAndroid Build Coastguard Worker   }
1441*795d594fSAndroid Build Coastguard Worker 
1442*795d594fSAndroid Build Coastguard Worker   unique_fd pidfd = PidfdOpen(in_pid, /*flags=*/0);
1443*795d594fSAndroid Build Coastguard Worker   if (pidfd < 0) {
1444*795d594fSAndroid Build Coastguard Worker     if (errno == ESRCH) {
1445*795d594fSAndroid Build Coastguard Worker       // The process has gone now.
1446*795d594fSAndroid Build Coastguard Worker       LOG(INFO) << ART_FORMAT("Process exited without sending notification '{}'", path);
1447*795d594fSAndroid Build Coastguard Worker       *_aidl_return = ndk::SharedRefBase::make<ArtdNotification>();
1448*795d594fSAndroid Build Coastguard Worker       return ScopedAStatus::ok();
1449*795d594fSAndroid Build Coastguard Worker     }
1450*795d594fSAndroid Build Coastguard Worker     return NonFatal(ART_FORMAT("Failed to pidfd_open {}: {}", in_pid, strerror(errno)));
1451*795d594fSAndroid Build Coastguard Worker   }
1452*795d594fSAndroid Build Coastguard Worker 
1453*795d594fSAndroid Build Coastguard Worker   *_aidl_return = ndk::SharedRefBase::make<ArtdNotification>(
1454*795d594fSAndroid Build Coastguard Worker       poll_, path, std::move(inotify_fd), std::move(pidfd));
1455*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
1456*795d594fSAndroid Build Coastguard Worker }
1457*795d594fSAndroid Build Coastguard Worker 
wait(int in_timeoutMs,bool * _aidl_return)1458*795d594fSAndroid Build Coastguard Worker ScopedAStatus ArtdNotification::wait(int in_timeoutMs, bool* _aidl_return) {
1459*795d594fSAndroid Build Coastguard Worker   auto cleanup = make_scope_guard([&, this] { CleanUp(); });
1460*795d594fSAndroid Build Coastguard Worker 
1461*795d594fSAndroid Build Coastguard Worker   if (!mu_.try_lock()) {
1462*795d594fSAndroid Build Coastguard Worker     return Fatal("`wait` can be called only once");
1463*795d594fSAndroid Build Coastguard Worker   }
1464*795d594fSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> lock(mu_, std::adopt_lock);
1465*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << ART_FORMAT("Waiting for notification '{}'", path_);
1466*795d594fSAndroid Build Coastguard Worker 
1467*795d594fSAndroid Build Coastguard Worker   if (is_called_) {
1468*795d594fSAndroid Build Coastguard Worker     return Fatal("`wait` can be called only once");
1469*795d594fSAndroid Build Coastguard Worker   }
1470*795d594fSAndroid Build Coastguard Worker   is_called_ = true;
1471*795d594fSAndroid Build Coastguard Worker 
1472*795d594fSAndroid Build Coastguard Worker   if (done_) {
1473*795d594fSAndroid Build Coastguard Worker     *_aidl_return = true;
1474*795d594fSAndroid Build Coastguard Worker     return ScopedAStatus::ok();
1475*795d594fSAndroid Build Coastguard Worker   }
1476*795d594fSAndroid Build Coastguard Worker 
1477*795d594fSAndroid Build Coastguard Worker   struct pollfd pollfds[2]{
1478*795d594fSAndroid Build Coastguard Worker       {.fd = inotify_fd_.get(), .events = POLLIN},
1479*795d594fSAndroid Build Coastguard Worker       {.fd = pidfd_.get(), .events = POLLIN},
1480*795d594fSAndroid Build Coastguard Worker   };
1481*795d594fSAndroid Build Coastguard Worker 
1482*795d594fSAndroid Build Coastguard Worker   constexpr size_t kBufSize = sizeof(struct inotify_event) + NAME_MAX + 1;
1483*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<uint8_t[]> buf(new (std::align_val_t(alignof(struct inotify_event)))
1484*795d594fSAndroid Build Coastguard Worker                                      uint8_t[kBufSize]);
1485*795d594fSAndroid Build Coastguard Worker   std::string basename = Basename(path_);
1486*795d594fSAndroid Build Coastguard Worker 
1487*795d594fSAndroid Build Coastguard Worker   uint64_t start_time = MilliTime();
1488*795d594fSAndroid Build Coastguard Worker   int64_t remaining_time_ms = in_timeoutMs;
1489*795d594fSAndroid Build Coastguard Worker   while (remaining_time_ms > 0) {
1490*795d594fSAndroid Build Coastguard Worker     int ret = TEMP_FAILURE_RETRY(poll_(pollfds, arraysize(pollfds), remaining_time_ms));
1491*795d594fSAndroid Build Coastguard Worker     if (ret < 0) {
1492*795d594fSAndroid Build Coastguard Worker       return NonFatal(
1493*795d594fSAndroid Build Coastguard Worker           ART_FORMAT("Failed to poll to wait for notification '{}': {}", path_, strerror(errno)));
1494*795d594fSAndroid Build Coastguard Worker     }
1495*795d594fSAndroid Build Coastguard Worker     if (ret == 0) {
1496*795d594fSAndroid Build Coastguard Worker       // Timeout.
1497*795d594fSAndroid Build Coastguard Worker       break;
1498*795d594fSAndroid Build Coastguard Worker     }
1499*795d594fSAndroid Build Coastguard Worker     if ((pollfds[0].revents & POLLIN) != 0) {
1500*795d594fSAndroid Build Coastguard Worker       ssize_t len = TEMP_FAILURE_RETRY(read(inotify_fd_, buf.get(), kBufSize));
1501*795d594fSAndroid Build Coastguard Worker       if (len < 0) {
1502*795d594fSAndroid Build Coastguard Worker         return NonFatal(ART_FORMAT(
1503*795d594fSAndroid Build Coastguard Worker             "Failed to read inotify fd for notification '{}': {}", path_, strerror(errno)));
1504*795d594fSAndroid Build Coastguard Worker       }
1505*795d594fSAndroid Build Coastguard Worker       const struct inotify_event* event;
1506*795d594fSAndroid Build Coastguard Worker       for (uint8_t* ptr = buf.get(); ptr < buf.get() + len;
1507*795d594fSAndroid Build Coastguard Worker            ptr += sizeof(struct inotify_event) + event->len) {
1508*795d594fSAndroid Build Coastguard Worker         event = (const struct inotify_event*)ptr;
1509*795d594fSAndroid Build Coastguard Worker         if (event->len > 0 && event->name == basename) {
1510*795d594fSAndroid Build Coastguard Worker           LOG(INFO) << ART_FORMAT("Received notification '{}'", path_);
1511*795d594fSAndroid Build Coastguard Worker           *_aidl_return = true;
1512*795d594fSAndroid Build Coastguard Worker           return ScopedAStatus::ok();
1513*795d594fSAndroid Build Coastguard Worker         }
1514*795d594fSAndroid Build Coastguard Worker       }
1515*795d594fSAndroid Build Coastguard Worker       remaining_time_ms = in_timeoutMs - (MilliTime() - start_time);
1516*795d594fSAndroid Build Coastguard Worker       continue;
1517*795d594fSAndroid Build Coastguard Worker     }
1518*795d594fSAndroid Build Coastguard Worker     if ((pollfds[1].revents & POLLIN) != 0) {
1519*795d594fSAndroid Build Coastguard Worker       LOG(INFO) << ART_FORMAT("Process exited without sending notification '{}'", path_);
1520*795d594fSAndroid Build Coastguard Worker       *_aidl_return = true;
1521*795d594fSAndroid Build Coastguard Worker       return ScopedAStatus::ok();
1522*795d594fSAndroid Build Coastguard Worker     }
1523*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << "Unreachable code";
1524*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
1525*795d594fSAndroid Build Coastguard Worker   }
1526*795d594fSAndroid Build Coastguard Worker 
1527*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << ART_FORMAT("Timed out while waiting for notification '{}'", path_);
1528*795d594fSAndroid Build Coastguard Worker   *_aidl_return = false;
1529*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
1530*795d594fSAndroid Build Coastguard Worker }
1531*795d594fSAndroid Build Coastguard Worker 
~ArtdNotification()1532*795d594fSAndroid Build Coastguard Worker ArtdNotification::~ArtdNotification() { CleanUp(); }
1533*795d594fSAndroid Build Coastguard Worker 
CleanUp()1534*795d594fSAndroid Build Coastguard Worker void ArtdNotification::CleanUp() {
1535*795d594fSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> lock(mu_);
1536*795d594fSAndroid Build Coastguard Worker   inotify_fd_.reset();
1537*795d594fSAndroid Build Coastguard Worker   pidfd_.reset();
1538*795d594fSAndroid Build Coastguard Worker }
1539*795d594fSAndroid Build Coastguard Worker 
commitPreRebootStagedFiles(const std::vector<ArtifactsPath> & in_artifacts,const std::vector<WritableProfilePath> & in_profiles,bool * _aidl_return)1540*795d594fSAndroid Build Coastguard Worker ScopedAStatus Artd::commitPreRebootStagedFiles(const std::vector<ArtifactsPath>& in_artifacts,
1541*795d594fSAndroid Build Coastguard Worker                                                const std::vector<WritableProfilePath>& in_profiles,
1542*795d594fSAndroid Build Coastguard Worker                                                bool* _aidl_return) {
1543*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_PRE_REBOOT(options_);
1544*795d594fSAndroid Build Coastguard Worker 
1545*795d594fSAndroid Build Coastguard Worker   std::vector<std::pair<std::string, std::string>> files_to_move;
1546*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> files_to_remove;
1547*795d594fSAndroid Build Coastguard Worker 
1548*795d594fSAndroid Build Coastguard Worker   for (const ArtifactsPath& artifacts : in_artifacts) {
1549*795d594fSAndroid Build Coastguard Worker     RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(artifacts, "artifacts");
1550*795d594fSAndroid Build Coastguard Worker 
1551*795d594fSAndroid Build Coastguard Worker     ArtifactsPath pre_reboot_artifacts = artifacts;
1552*795d594fSAndroid Build Coastguard Worker     pre_reboot_artifacts.isPreReboot = true;
1553*795d594fSAndroid Build Coastguard Worker 
1554*795d594fSAndroid Build Coastguard Worker     auto src_artifacts = std::make_unique<RawArtifactsPath>(
1555*795d594fSAndroid Build Coastguard Worker         OR_RETURN_FATAL(BuildArtifactsPath(pre_reboot_artifacts)));
1556*795d594fSAndroid Build Coastguard Worker     auto dst_artifacts =
1557*795d594fSAndroid Build Coastguard Worker         std::make_unique<RawArtifactsPath>(OR_RETURN_FATAL(BuildArtifactsPath(artifacts)));
1558*795d594fSAndroid Build Coastguard Worker 
1559*795d594fSAndroid Build Coastguard Worker     if (OS::FileExists(src_artifacts->oat_path.c_str())) {
1560*795d594fSAndroid Build Coastguard Worker       files_to_move.emplace_back(src_artifacts->oat_path, dst_artifacts->oat_path);
1561*795d594fSAndroid Build Coastguard Worker       files_to_move.emplace_back(src_artifacts->vdex_path, dst_artifacts->vdex_path);
1562*795d594fSAndroid Build Coastguard Worker       if (OS::FileExists(src_artifacts->art_path.c_str())) {
1563*795d594fSAndroid Build Coastguard Worker         files_to_move.emplace_back(src_artifacts->art_path, dst_artifacts->art_path);
1564*795d594fSAndroid Build Coastguard Worker       } else {
1565*795d594fSAndroid Build Coastguard Worker         files_to_remove.push_back(dst_artifacts->art_path);
1566*795d594fSAndroid Build Coastguard Worker       }
1567*795d594fSAndroid Build Coastguard Worker     }
1568*795d594fSAndroid Build Coastguard Worker   }
1569*795d594fSAndroid Build Coastguard Worker 
1570*795d594fSAndroid Build Coastguard Worker   for (const WritableProfilePath& profile : in_profiles) {
1571*795d594fSAndroid Build Coastguard Worker     RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(profile, "profiles");
1572*795d594fSAndroid Build Coastguard Worker 
1573*795d594fSAndroid Build Coastguard Worker     WritableProfilePath pre_reboot_profile = profile;
1574*795d594fSAndroid Build Coastguard Worker     PreRebootFlag(pre_reboot_profile) = true;
1575*795d594fSAndroid Build Coastguard Worker 
1576*795d594fSAndroid Build Coastguard Worker     auto src_profile = std::make_unique<std::string>(
1577*795d594fSAndroid Build Coastguard Worker         OR_RETURN_FATAL(BuildWritableProfilePath(pre_reboot_profile)));
1578*795d594fSAndroid Build Coastguard Worker     auto dst_profile =
1579*795d594fSAndroid Build Coastguard Worker         std::make_unique<std::string>(OR_RETURN_FATAL(BuildWritableProfilePath(profile)));
1580*795d594fSAndroid Build Coastguard Worker 
1581*795d594fSAndroid Build Coastguard Worker     if (OS::FileExists(src_profile->c_str())) {
1582*795d594fSAndroid Build Coastguard Worker       files_to_move.emplace_back(*src_profile, *dst_profile);
1583*795d594fSAndroid Build Coastguard Worker     }
1584*795d594fSAndroid Build Coastguard Worker   }
1585*795d594fSAndroid Build Coastguard Worker 
1586*795d594fSAndroid Build Coastguard Worker   OR_RETURN_NON_FATAL(MoveAllOrAbandon(files_to_move, files_to_remove));
1587*795d594fSAndroid Build Coastguard Worker 
1588*795d594fSAndroid Build Coastguard Worker   for (const auto& [src_path, dst_path] : files_to_move) {
1589*795d594fSAndroid Build Coastguard Worker     LOG(INFO) << ART_FORMAT("Committed Pre-reboot staged file '{}' to '{}'", src_path, dst_path);
1590*795d594fSAndroid Build Coastguard Worker   }
1591*795d594fSAndroid Build Coastguard Worker 
1592*795d594fSAndroid Build Coastguard Worker   *_aidl_return = !files_to_move.empty();
1593*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
1594*795d594fSAndroid Build Coastguard Worker }
1595*795d594fSAndroid Build Coastguard Worker 
checkPreRebootSystemRequirements(const std::string & in_chrootDir,bool * _aidl_return)1596*795d594fSAndroid Build Coastguard Worker ScopedAStatus Artd::checkPreRebootSystemRequirements(const std::string& in_chrootDir,
1597*795d594fSAndroid Build Coastguard Worker                                                      bool* _aidl_return) {
1598*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_PRE_REBOOT(options_);
1599*795d594fSAndroid Build Coastguard Worker   BuildSystemProperties new_props =
1600*795d594fSAndroid Build Coastguard Worker       OR_RETURN_NON_FATAL(BuildSystemProperties::Create(in_chrootDir + "/system/build.prop"));
1601*795d594fSAndroid Build Coastguard Worker   std::string old_release_str = props_->GetOrEmpty("ro.build.version.release");
1602*795d594fSAndroid Build Coastguard Worker   int old_release;
1603*795d594fSAndroid Build Coastguard Worker   if (!ParseInt(old_release_str, &old_release)) {
1604*795d594fSAndroid Build Coastguard Worker     return NonFatal(
1605*795d594fSAndroid Build Coastguard Worker         ART_FORMAT("Failed to read or parse old release number, got '{}'", old_release_str));
1606*795d594fSAndroid Build Coastguard Worker   }
1607*795d594fSAndroid Build Coastguard Worker   std::string new_release_str = new_props.GetOrEmpty("ro.build.version.release");
1608*795d594fSAndroid Build Coastguard Worker   int new_release;
1609*795d594fSAndroid Build Coastguard Worker   if (!ParseInt(new_release_str, &new_release)) {
1610*795d594fSAndroid Build Coastguard Worker     return NonFatal(
1611*795d594fSAndroid Build Coastguard Worker         ART_FORMAT("Failed to read or parse new release number, got '{}'", new_release_str));
1612*795d594fSAndroid Build Coastguard Worker   }
1613*795d594fSAndroid Build Coastguard Worker   if (new_release - old_release >= 2) {
1614*795d594fSAndroid Build Coastguard Worker     // When the release version difference is large, there is no particular technical reason why we
1615*795d594fSAndroid Build Coastguard Worker     // can't run Pre-reboot Dexopt, but we cannot test and support those cases.
1616*795d594fSAndroid Build Coastguard Worker     LOG(WARNING) << ART_FORMAT(
1617*795d594fSAndroid Build Coastguard Worker         "Pre-reboot Dexopt not supported due to large difference in release versions (old_release: "
1618*795d594fSAndroid Build Coastguard Worker         "{}, new_release: {})",
1619*795d594fSAndroid Build Coastguard Worker         old_release,
1620*795d594fSAndroid Build Coastguard Worker         new_release);
1621*795d594fSAndroid Build Coastguard Worker     *_aidl_return = false;
1622*795d594fSAndroid Build Coastguard Worker     return ScopedAStatus::ok();
1623*795d594fSAndroid Build Coastguard Worker   }
1624*795d594fSAndroid Build Coastguard Worker 
1625*795d594fSAndroid Build Coastguard Worker   *_aidl_return = true;
1626*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
1627*795d594fSAndroid Build Coastguard Worker }
1628*795d594fSAndroid Build Coastguard Worker 
Start()1629*795d594fSAndroid Build Coastguard Worker Result<void> Artd::Start() {
1630*795d594fSAndroid Build Coastguard Worker   OR_RETURN(SetLogVerbosity());
1631*795d594fSAndroid Build Coastguard Worker   MemMap::Init();
1632*795d594fSAndroid Build Coastguard Worker   Runtime::AllowPageSizeAccess();
1633*795d594fSAndroid Build Coastguard Worker 
1634*795d594fSAndroid Build Coastguard Worker   ScopedAStatus status = ScopedAStatus::fromStatus(AServiceManager_registerLazyService(
1635*795d594fSAndroid Build Coastguard Worker       this->asBinder().get(), options_.is_pre_reboot ? kPreRebootServiceName : kServiceName));
1636*795d594fSAndroid Build Coastguard Worker   if (!status.isOk()) {
1637*795d594fSAndroid Build Coastguard Worker     return Error() << status.getDescription();
1638*795d594fSAndroid Build Coastguard Worker   }
1639*795d594fSAndroid Build Coastguard Worker 
1640*795d594fSAndroid Build Coastguard Worker   ABinderProcess_startThreadPool();
1641*795d594fSAndroid Build Coastguard Worker 
1642*795d594fSAndroid Build Coastguard Worker   return {};
1643*795d594fSAndroid Build Coastguard Worker }
1644*795d594fSAndroid Build Coastguard Worker 
GetOatFileAssistantContext()1645*795d594fSAndroid Build Coastguard Worker Result<OatFileAssistantContext*> Artd::GetOatFileAssistantContext() {
1646*795d594fSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> lock(ofa_context_mu_);
1647*795d594fSAndroid Build Coastguard Worker 
1648*795d594fSAndroid Build Coastguard Worker   if (ofa_context_ == nullptr) {
1649*795d594fSAndroid Build Coastguard Worker     ofa_context_ = std::make_unique<OatFileAssistantContext>(
1650*795d594fSAndroid Build Coastguard Worker         std::make_unique<OatFileAssistantContext::RuntimeOptions>(
1651*795d594fSAndroid Build Coastguard Worker             OatFileAssistantContext::RuntimeOptions{
1652*795d594fSAndroid Build Coastguard Worker                 .image_locations = *OR_RETURN(GetBootImageLocations()),
1653*795d594fSAndroid Build Coastguard Worker                 .boot_class_path = *OR_RETURN(GetBootClassPath()),
1654*795d594fSAndroid Build Coastguard Worker                 .boot_class_path_locations = *OR_RETURN(GetBootClassPath()),
1655*795d594fSAndroid Build Coastguard Worker                 .deny_art_apex_data_files = DenyArtApexDataFiles(),
1656*795d594fSAndroid Build Coastguard Worker             }));
1657*795d594fSAndroid Build Coastguard Worker     std::string error_msg;
1658*795d594fSAndroid Build Coastguard Worker     if (!ofa_context_->FetchAll(&error_msg)) {
1659*795d594fSAndroid Build Coastguard Worker       return Error() << error_msg;
1660*795d594fSAndroid Build Coastguard Worker     }
1661*795d594fSAndroid Build Coastguard Worker   }
1662*795d594fSAndroid Build Coastguard Worker 
1663*795d594fSAndroid Build Coastguard Worker   return ofa_context_.get();
1664*795d594fSAndroid Build Coastguard Worker }
1665*795d594fSAndroid Build Coastguard Worker 
GetBootImageLocations()1666*795d594fSAndroid Build Coastguard Worker Result<const std::vector<std::string>*> Artd::GetBootImageLocations() {
1667*795d594fSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> lock(cache_mu_);
1668*795d594fSAndroid Build Coastguard Worker 
1669*795d594fSAndroid Build Coastguard Worker   if (!cached_boot_image_locations_.has_value()) {
1670*795d594fSAndroid Build Coastguard Worker     std::string location_str;
1671*795d594fSAndroid Build Coastguard Worker 
1672*795d594fSAndroid Build Coastguard Worker     if (UseJitZygoteLocked()) {
1673*795d594fSAndroid Build Coastguard Worker       location_str = GetJitZygoteBootImageLocation();
1674*795d594fSAndroid Build Coastguard Worker     } else if (std::string value = GetUserDefinedBootImageLocationsLocked(); !value.empty()) {
1675*795d594fSAndroid Build Coastguard Worker       location_str = std::move(value);
1676*795d594fSAndroid Build Coastguard Worker     } else {
1677*795d594fSAndroid Build Coastguard Worker       std::string error_msg;
1678*795d594fSAndroid Build Coastguard Worker       std::string android_root = GetAndroidRootSafe(&error_msg);
1679*795d594fSAndroid Build Coastguard Worker       if (!error_msg.empty()) {
1680*795d594fSAndroid Build Coastguard Worker         return Errorf("Failed to get ANDROID_ROOT: {}", error_msg);
1681*795d594fSAndroid Build Coastguard Worker       }
1682*795d594fSAndroid Build Coastguard Worker       location_str = GetDefaultBootImageLocation(android_root, DenyArtApexDataFilesLocked());
1683*795d594fSAndroid Build Coastguard Worker     }
1684*795d594fSAndroid Build Coastguard Worker 
1685*795d594fSAndroid Build Coastguard Worker     cached_boot_image_locations_ = Split(location_str, ":");
1686*795d594fSAndroid Build Coastguard Worker   }
1687*795d594fSAndroid Build Coastguard Worker 
1688*795d594fSAndroid Build Coastguard Worker   return &cached_boot_image_locations_.value();
1689*795d594fSAndroid Build Coastguard Worker }
1690*795d594fSAndroid Build Coastguard Worker 
GetBootClassPath()1691*795d594fSAndroid Build Coastguard Worker Result<const std::vector<std::string>*> Artd::GetBootClassPath() {
1692*795d594fSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> lock(cache_mu_);
1693*795d594fSAndroid Build Coastguard Worker 
1694*795d594fSAndroid Build Coastguard Worker   if (!cached_boot_class_path_.has_value()) {
1695*795d594fSAndroid Build Coastguard Worker     const char* env_value = getenv("BOOTCLASSPATH");
1696*795d594fSAndroid Build Coastguard Worker     if (env_value == nullptr || strlen(env_value) == 0) {
1697*795d594fSAndroid Build Coastguard Worker       return Errorf("Failed to get environment variable 'BOOTCLASSPATH'");
1698*795d594fSAndroid Build Coastguard Worker     }
1699*795d594fSAndroid Build Coastguard Worker     cached_boot_class_path_ = Split(env_value, ":");
1700*795d594fSAndroid Build Coastguard Worker   }
1701*795d594fSAndroid Build Coastguard Worker 
1702*795d594fSAndroid Build Coastguard Worker   return &cached_boot_class_path_.value();
1703*795d594fSAndroid Build Coastguard Worker }
1704*795d594fSAndroid Build Coastguard Worker 
UseJitZygote()1705*795d594fSAndroid Build Coastguard Worker bool Artd::UseJitZygote() {
1706*795d594fSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> lock(cache_mu_);
1707*795d594fSAndroid Build Coastguard Worker   return UseJitZygoteLocked();
1708*795d594fSAndroid Build Coastguard Worker }
1709*795d594fSAndroid Build Coastguard Worker 
UseJitZygoteLocked()1710*795d594fSAndroid Build Coastguard Worker bool Artd::UseJitZygoteLocked() {
1711*795d594fSAndroid Build Coastguard Worker   if (!cached_use_jit_zygote_.has_value()) {
1712*795d594fSAndroid Build Coastguard Worker     cached_use_jit_zygote_ =
1713*795d594fSAndroid Build Coastguard Worker         props_->GetBool("persist.device_config.runtime_native_boot.profilebootclasspath",
1714*795d594fSAndroid Build Coastguard Worker                         "dalvik.vm.profilebootclasspath",
1715*795d594fSAndroid Build Coastguard Worker                         /*default_value=*/false);
1716*795d594fSAndroid Build Coastguard Worker   }
1717*795d594fSAndroid Build Coastguard Worker 
1718*795d594fSAndroid Build Coastguard Worker   return cached_use_jit_zygote_.value();
1719*795d594fSAndroid Build Coastguard Worker }
1720*795d594fSAndroid Build Coastguard Worker 
GetUserDefinedBootImageLocations()1721*795d594fSAndroid Build Coastguard Worker const std::string& Artd::GetUserDefinedBootImageLocations() {
1722*795d594fSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> lock(cache_mu_);
1723*795d594fSAndroid Build Coastguard Worker   return GetUserDefinedBootImageLocationsLocked();
1724*795d594fSAndroid Build Coastguard Worker }
1725*795d594fSAndroid Build Coastguard Worker 
GetUserDefinedBootImageLocationsLocked()1726*795d594fSAndroid Build Coastguard Worker const std::string& Artd::GetUserDefinedBootImageLocationsLocked() {
1727*795d594fSAndroid Build Coastguard Worker   if (!cached_user_defined_boot_image_locations_.has_value()) {
1728*795d594fSAndroid Build Coastguard Worker     cached_user_defined_boot_image_locations_ = props_->GetOrEmpty("dalvik.vm.boot-image");
1729*795d594fSAndroid Build Coastguard Worker   }
1730*795d594fSAndroid Build Coastguard Worker 
1731*795d594fSAndroid Build Coastguard Worker   return cached_user_defined_boot_image_locations_.value();
1732*795d594fSAndroid Build Coastguard Worker }
1733*795d594fSAndroid Build Coastguard Worker 
DenyArtApexDataFiles()1734*795d594fSAndroid Build Coastguard Worker bool Artd::DenyArtApexDataFiles() {
1735*795d594fSAndroid Build Coastguard Worker   std::lock_guard<std::mutex> lock(cache_mu_);
1736*795d594fSAndroid Build Coastguard Worker   return DenyArtApexDataFilesLocked();
1737*795d594fSAndroid Build Coastguard Worker }
1738*795d594fSAndroid Build Coastguard Worker 
DenyArtApexDataFilesLocked()1739*795d594fSAndroid Build Coastguard Worker bool Artd::DenyArtApexDataFilesLocked() {
1740*795d594fSAndroid Build Coastguard Worker   if (!cached_deny_art_apex_data_files_.has_value()) {
1741*795d594fSAndroid Build Coastguard Worker     cached_deny_art_apex_data_files_ =
1742*795d594fSAndroid Build Coastguard Worker         !props_->GetBool("odsign.verification.success", /*default_value=*/false);
1743*795d594fSAndroid Build Coastguard Worker   }
1744*795d594fSAndroid Build Coastguard Worker 
1745*795d594fSAndroid Build Coastguard Worker   return cached_deny_art_apex_data_files_.value();
1746*795d594fSAndroid Build Coastguard Worker }
1747*795d594fSAndroid Build Coastguard Worker 
GetProfman()1748*795d594fSAndroid Build Coastguard Worker Result<std::string> Artd::GetProfman() { return BuildArtBinPath("profman"); }
1749*795d594fSAndroid Build Coastguard Worker 
GetArtExecCmdlineBuilder()1750*795d594fSAndroid Build Coastguard Worker Result<CmdlineBuilder> Artd::GetArtExecCmdlineBuilder() {
1751*795d594fSAndroid Build Coastguard Worker   std::string art_exec_path = OR_RETURN(BuildArtBinPath("art_exec"));
1752*795d594fSAndroid Build Coastguard Worker   if (options_.is_pre_reboot) {
1753*795d594fSAndroid Build Coastguard Worker     // "/mnt/compat_env" is prepared by dexopt_chroot_setup on Android V.
1754*795d594fSAndroid Build Coastguard Worker     std::string compat_art_exec_path = "/mnt/compat_env" + art_exec_path;
1755*795d594fSAndroid Build Coastguard Worker     if (OS::FileExists(compat_art_exec_path.c_str())) {
1756*795d594fSAndroid Build Coastguard Worker       art_exec_path = std::move(compat_art_exec_path);
1757*795d594fSAndroid Build Coastguard Worker     }
1758*795d594fSAndroid Build Coastguard Worker   }
1759*795d594fSAndroid Build Coastguard Worker 
1760*795d594fSAndroid Build Coastguard Worker   CmdlineBuilder args;
1761*795d594fSAndroid Build Coastguard Worker   args.Add(art_exec_path)
1762*795d594fSAndroid Build Coastguard Worker       .Add("--drop-capabilities")
1763*795d594fSAndroid Build Coastguard Worker       .AddIf(options_.is_pre_reboot, "--process-name-suffix=Pre-reboot Dexopt chroot");
1764*795d594fSAndroid Build Coastguard Worker   return args;
1765*795d594fSAndroid Build Coastguard Worker }
1766*795d594fSAndroid Build Coastguard Worker 
ShouldUseDex2Oat64()1767*795d594fSAndroid Build Coastguard Worker bool Artd::ShouldUseDex2Oat64() {
1768*795d594fSAndroid Build Coastguard Worker   return !props_->GetOrEmpty("ro.product.cpu.abilist64").empty() &&
1769*795d594fSAndroid Build Coastguard Worker          props_->GetBool("dalvik.vm.dex2oat64.enabled", /*default_value=*/false);
1770*795d594fSAndroid Build Coastguard Worker }
1771*795d594fSAndroid Build Coastguard Worker 
ShouldUseDebugBinaries()1772*795d594fSAndroid Build Coastguard Worker bool Artd::ShouldUseDebugBinaries() {
1773*795d594fSAndroid Build Coastguard Worker   return props_->GetOrEmpty("persist.sys.dalvik.vm.lib.2") == "libartd.so";
1774*795d594fSAndroid Build Coastguard Worker }
1775*795d594fSAndroid Build Coastguard Worker 
GetDex2Oat()1776*795d594fSAndroid Build Coastguard Worker Result<std::string> Artd::GetDex2Oat() {
1777*795d594fSAndroid Build Coastguard Worker   std::string binary_name = ShouldUseDebugBinaries() ?
1778*795d594fSAndroid Build Coastguard Worker                                 (ShouldUseDex2Oat64() ? "dex2oatd64" : "dex2oatd32") :
1779*795d594fSAndroid Build Coastguard Worker                                 (ShouldUseDex2Oat64() ? "dex2oat64" : "dex2oat32");
1780*795d594fSAndroid Build Coastguard Worker   return BuildArtBinPath(binary_name);
1781*795d594fSAndroid Build Coastguard Worker }
1782*795d594fSAndroid Build Coastguard Worker 
ShouldCreateSwapFileForDexopt()1783*795d594fSAndroid Build Coastguard Worker bool Artd::ShouldCreateSwapFileForDexopt() {
1784*795d594fSAndroid Build Coastguard Worker   // Create a swap file by default. Dex2oat will decide whether to use it or not.
1785*795d594fSAndroid Build Coastguard Worker   return props_->GetBool("dalvik.vm.dex2oat-swap", /*default_value=*/true);
1786*795d594fSAndroid Build Coastguard Worker }
1787*795d594fSAndroid Build Coastguard Worker 
AddBootImageFlags(CmdlineBuilder & args)1788*795d594fSAndroid Build Coastguard Worker void Artd::AddBootImageFlags(/*out*/ CmdlineBuilder& args) {
1789*795d594fSAndroid Build Coastguard Worker   if (UseJitZygote()) {
1790*795d594fSAndroid Build Coastguard Worker     args.Add("--force-jit-zygote");
1791*795d594fSAndroid Build Coastguard Worker   } else {
1792*795d594fSAndroid Build Coastguard Worker     args.AddIfNonEmpty("--boot-image=%s", GetUserDefinedBootImageLocations());
1793*795d594fSAndroid Build Coastguard Worker   }
1794*795d594fSAndroid Build Coastguard Worker }
1795*795d594fSAndroid Build Coastguard Worker 
AddCompilerConfigFlags(const std::string & instruction_set,const std::string & compiler_filter,PriorityClass priority_class,const DexoptOptions & dexopt_options,CmdlineBuilder & args)1796*795d594fSAndroid Build Coastguard Worker void Artd::AddCompilerConfigFlags(const std::string& instruction_set,
1797*795d594fSAndroid Build Coastguard Worker                                   const std::string& compiler_filter,
1798*795d594fSAndroid Build Coastguard Worker                                   PriorityClass priority_class,
1799*795d594fSAndroid Build Coastguard Worker                                   const DexoptOptions& dexopt_options,
1800*795d594fSAndroid Build Coastguard Worker                                   /*out*/ CmdlineBuilder& args) {
1801*795d594fSAndroid Build Coastguard Worker   args.Add("--instruction-set=%s", instruction_set);
1802*795d594fSAndroid Build Coastguard Worker   std::string features_prop = ART_FORMAT("dalvik.vm.isa.{}.features", instruction_set);
1803*795d594fSAndroid Build Coastguard Worker   args.AddIfNonEmpty("--instruction-set-features=%s", props_->GetOrEmpty(features_prop));
1804*795d594fSAndroid Build Coastguard Worker   std::string variant_prop = ART_FORMAT("dalvik.vm.isa.{}.variant", instruction_set);
1805*795d594fSAndroid Build Coastguard Worker   args.AddIfNonEmpty("--instruction-set-variant=%s", props_->GetOrEmpty(variant_prop));
1806*795d594fSAndroid Build Coastguard Worker 
1807*795d594fSAndroid Build Coastguard Worker   args.Add("--compiler-filter=%s", compiler_filter)
1808*795d594fSAndroid Build Coastguard Worker       .Add("--compilation-reason=%s", dexopt_options.compilationReason);
1809*795d594fSAndroid Build Coastguard Worker 
1810*795d594fSAndroid Build Coastguard Worker   args.AddIf(priority_class >= PriorityClass::INTERACTIVE, "--compact-dex-level=none");
1811*795d594fSAndroid Build Coastguard Worker 
1812*795d594fSAndroid Build Coastguard Worker   args.AddIfNonEmpty("--max-image-block-size=%s",
1813*795d594fSAndroid Build Coastguard Worker                      props_->GetOrEmpty("dalvik.vm.dex2oat-max-image-block-size"))
1814*795d594fSAndroid Build Coastguard Worker       .AddIfNonEmpty("--very-large-app-threshold=%s",
1815*795d594fSAndroid Build Coastguard Worker                      props_->GetOrEmpty("dalvik.vm.dex2oat-very-large"))
1816*795d594fSAndroid Build Coastguard Worker       .AddIfNonEmpty("--resolve-startup-const-strings=%s",
1817*795d594fSAndroid Build Coastguard Worker                      props_->GetOrEmpty("dalvik.vm.dex2oat-resolve-startup-strings"));
1818*795d594fSAndroid Build Coastguard Worker 
1819*795d594fSAndroid Build Coastguard Worker   args.AddIf(dexopt_options.debuggable, "--debuggable")
1820*795d594fSAndroid Build Coastguard Worker       .AddIf(props_->GetBool("debug.generate-debug-info", /*default_value=*/false),
1821*795d594fSAndroid Build Coastguard Worker              "--generate-debug-info")
1822*795d594fSAndroid Build Coastguard Worker       .AddIf(props_->GetBool("dalvik.vm.dex2oat-minidebuginfo", /*default_value=*/false),
1823*795d594fSAndroid Build Coastguard Worker              "--generate-mini-debug-info");
1824*795d594fSAndroid Build Coastguard Worker 
1825*795d594fSAndroid Build Coastguard Worker   args.AddRuntimeIf(DenyArtApexDataFiles(), "-Xdeny-art-apex-data-files")
1826*795d594fSAndroid Build Coastguard Worker       .AddRuntime("-Xtarget-sdk-version:%d", dexopt_options.targetSdkVersion)
1827*795d594fSAndroid Build Coastguard Worker       .AddRuntimeIf(dexopt_options.hiddenApiPolicyEnabled, "-Xhidden-api-policy:enabled");
1828*795d594fSAndroid Build Coastguard Worker }
1829*795d594fSAndroid Build Coastguard Worker 
AddPerfConfigFlags(PriorityClass priority_class,CmdlineBuilder & art_exec_args,CmdlineBuilder & dex2oat_args)1830*795d594fSAndroid Build Coastguard Worker void Artd::AddPerfConfigFlags(PriorityClass priority_class,
1831*795d594fSAndroid Build Coastguard Worker                               /*out*/ CmdlineBuilder& art_exec_args,
1832*795d594fSAndroid Build Coastguard Worker                               /*out*/ CmdlineBuilder& dex2oat_args) {
1833*795d594fSAndroid Build Coastguard Worker   // CPU set and number of threads.
1834*795d594fSAndroid Build Coastguard Worker   std::string default_cpu_set_prop = "dalvik.vm.dex2oat-cpu-set";
1835*795d594fSAndroid Build Coastguard Worker   std::string default_threads_prop = "dalvik.vm.dex2oat-threads";
1836*795d594fSAndroid Build Coastguard Worker   std::string cpu_set;
1837*795d594fSAndroid Build Coastguard Worker   std::string threads;
1838*795d594fSAndroid Build Coastguard Worker   if (priority_class >= PriorityClass::BOOT) {
1839*795d594fSAndroid Build Coastguard Worker     cpu_set = props_->GetOrEmpty("dalvik.vm.boot-dex2oat-cpu-set");
1840*795d594fSAndroid Build Coastguard Worker     threads = props_->GetOrEmpty("dalvik.vm.boot-dex2oat-threads");
1841*795d594fSAndroid Build Coastguard Worker   } else if (priority_class >= PriorityClass::INTERACTIVE_FAST) {
1842*795d594fSAndroid Build Coastguard Worker     cpu_set = props_->GetOrEmpty("dalvik.vm.restore-dex2oat-cpu-set", default_cpu_set_prop);
1843*795d594fSAndroid Build Coastguard Worker     threads = props_->GetOrEmpty("dalvik.vm.restore-dex2oat-threads", default_threads_prop);
1844*795d594fSAndroid Build Coastguard Worker   } else if (priority_class <= PriorityClass::BACKGROUND) {
1845*795d594fSAndroid Build Coastguard Worker     cpu_set = props_->GetOrEmpty("dalvik.vm.background-dex2oat-cpu-set", default_cpu_set_prop);
1846*795d594fSAndroid Build Coastguard Worker     threads = props_->GetOrEmpty("dalvik.vm.background-dex2oat-threads", default_threads_prop);
1847*795d594fSAndroid Build Coastguard Worker   } else {
1848*795d594fSAndroid Build Coastguard Worker     cpu_set = props_->GetOrEmpty(default_cpu_set_prop);
1849*795d594fSAndroid Build Coastguard Worker     threads = props_->GetOrEmpty(default_threads_prop);
1850*795d594fSAndroid Build Coastguard Worker   }
1851*795d594fSAndroid Build Coastguard Worker   dex2oat_args.AddIfNonEmpty("--cpu-set=%s", cpu_set).AddIfNonEmpty("-j%s", threads);
1852*795d594fSAndroid Build Coastguard Worker 
1853*795d594fSAndroid Build Coastguard Worker   if (priority_class < PriorityClass::BOOT) {
1854*795d594fSAndroid Build Coastguard Worker     art_exec_args
1855*795d594fSAndroid Build Coastguard Worker         .Add(priority_class <= PriorityClass::BACKGROUND ? "--set-task-profile=Dex2OatBackground" :
1856*795d594fSAndroid Build Coastguard Worker                                                            "--set-task-profile=Dex2OatBootComplete")
1857*795d594fSAndroid Build Coastguard Worker         .Add("--set-priority=background");
1858*795d594fSAndroid Build Coastguard Worker   }
1859*795d594fSAndroid Build Coastguard Worker 
1860*795d594fSAndroid Build Coastguard Worker   dex2oat_args.AddRuntimeIfNonEmpty("-Xms%s", props_->GetOrEmpty("dalvik.vm.dex2oat-Xms"))
1861*795d594fSAndroid Build Coastguard Worker       .AddRuntimeIfNonEmpty("-Xmx%s", props_->GetOrEmpty("dalvik.vm.dex2oat-Xmx"));
1862*795d594fSAndroid Build Coastguard Worker 
1863*795d594fSAndroid Build Coastguard Worker   // Enable compiling dex files in isolation on low ram devices.
1864*795d594fSAndroid Build Coastguard Worker   // It takes longer but reduces the memory footprint.
1865*795d594fSAndroid Build Coastguard Worker   dex2oat_args.AddIf(props_->GetBool("ro.config.low_ram", /*default_value=*/false),
1866*795d594fSAndroid Build Coastguard Worker                      "--compile-individually");
1867*795d594fSAndroid Build Coastguard Worker 
1868*795d594fSAndroid Build Coastguard Worker   for (const std::string& flag :
1869*795d594fSAndroid Build Coastguard Worker        Tokenize(props_->GetOrEmpty("dalvik.vm.dex2oat-flags"), /*delimiters=*/" ")) {
1870*795d594fSAndroid Build Coastguard Worker     dex2oat_args.AddIfNonEmpty("%s", flag);
1871*795d594fSAndroid Build Coastguard Worker   }
1872*795d594fSAndroid Build Coastguard Worker }
1873*795d594fSAndroid Build Coastguard Worker 
ExecAndReturnCode(const std::vector<std::string> & args,int timeout_sec,const ExecCallbacks & callbacks,ProcessStat * stat) const1874*795d594fSAndroid Build Coastguard Worker Result<int> Artd::ExecAndReturnCode(const std::vector<std::string>& args,
1875*795d594fSAndroid Build Coastguard Worker                                     int timeout_sec,
1876*795d594fSAndroid Build Coastguard Worker                                     const ExecCallbacks& callbacks,
1877*795d594fSAndroid Build Coastguard Worker                                     ProcessStat* stat) const {
1878*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
1879*795d594fSAndroid Build Coastguard Worker   // Create a new process group so that we can kill the process subtree at once by killing the
1880*795d594fSAndroid Build Coastguard Worker   // process group.
1881*795d594fSAndroid Build Coastguard Worker   ExecResult result = exec_utils_->ExecAndReturnResult(
1882*795d594fSAndroid Build Coastguard Worker       args, timeout_sec, callbacks, /*new_process_group=*/true, stat, &error_msg);
1883*795d594fSAndroid Build Coastguard Worker   if (result.status != ExecResult::kExited) {
1884*795d594fSAndroid Build Coastguard Worker     return Error() << error_msg;
1885*795d594fSAndroid Build Coastguard Worker   }
1886*795d594fSAndroid Build Coastguard Worker   return result.exit_code;
1887*795d594fSAndroid Build Coastguard Worker }
1888*795d594fSAndroid Build Coastguard Worker 
Fstat(const File & file) const1889*795d594fSAndroid Build Coastguard Worker Result<struct stat> Artd::Fstat(const File& file) const {
1890*795d594fSAndroid Build Coastguard Worker   struct stat st;
1891*795d594fSAndroid Build Coastguard Worker   if (fstat_(file.Fd(), &st) != 0) {
1892*795d594fSAndroid Build Coastguard Worker     return Errorf("Unable to fstat file '{}'", file.GetPath());
1893*795d594fSAndroid Build Coastguard Worker   }
1894*795d594fSAndroid Build Coastguard Worker   return st;
1895*795d594fSAndroid Build Coastguard Worker }
1896*795d594fSAndroid Build Coastguard Worker 
BindMountNewDir(const std::string & source,const std::string & target) const1897*795d594fSAndroid Build Coastguard Worker Result<void> Artd::BindMountNewDir(const std::string& source, const std::string& target) const {
1898*795d594fSAndroid Build Coastguard Worker   OR_RETURN(CreateDir(source));
1899*795d594fSAndroid Build Coastguard Worker   OR_RETURN(BindMount(source, target));
1900*795d594fSAndroid Build Coastguard Worker   OR_RETURN(restorecon_(target, /*se_context=*/std::nullopt, /*recurse=*/false));
1901*795d594fSAndroid Build Coastguard Worker   return {};
1902*795d594fSAndroid Build Coastguard Worker }
1903*795d594fSAndroid Build Coastguard Worker 
BindMount(const std::string & source,const std::string & target) const1904*795d594fSAndroid Build Coastguard Worker Result<void> Artd::BindMount(const std::string& source, const std::string& target) const {
1905*795d594fSAndroid Build Coastguard Worker   if (mount_(source.c_str(),
1906*795d594fSAndroid Build Coastguard Worker              target.c_str(),
1907*795d594fSAndroid Build Coastguard Worker              /*fs_type=*/nullptr,
1908*795d594fSAndroid Build Coastguard Worker              MS_BIND | MS_PRIVATE,
1909*795d594fSAndroid Build Coastguard Worker              /*data=*/nullptr) != 0) {
1910*795d594fSAndroid Build Coastguard Worker     return ErrnoErrorf("Failed to bind-mount '{}' at '{}'", source, target);
1911*795d594fSAndroid Build Coastguard Worker   }
1912*795d594fSAndroid Build Coastguard Worker   return {};
1913*795d594fSAndroid Build Coastguard Worker }
1914*795d594fSAndroid Build Coastguard Worker 
preRebootInit(const std::shared_ptr<IArtdCancellationSignal> & in_cancellationSignal,bool * _aidl_return)1915*795d594fSAndroid Build Coastguard Worker ScopedAStatus Artd::preRebootInit(
1916*795d594fSAndroid Build Coastguard Worker     const std::shared_ptr<IArtdCancellationSignal>& in_cancellationSignal, bool* _aidl_return) {
1917*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_NOT_PRE_REBOOT(options_);
1918*795d594fSAndroid Build Coastguard Worker 
1919*795d594fSAndroid Build Coastguard Worker   std::string tmp_dir = pre_reboot_tmp_dir_.value_or(kDefaultPreRebootTmpDir);
1920*795d594fSAndroid Build Coastguard Worker   std::string preparation_done_file = tmp_dir + "/preparation_done";
1921*795d594fSAndroid Build Coastguard Worker   std::string classpath_file = tmp_dir + "/classpath.txt";
1922*795d594fSAndroid Build Coastguard Worker   std::string art_apex_data_dir = tmp_dir + "/art_apex_data";
1923*795d594fSAndroid Build Coastguard Worker   std::string odrefresh_dir = tmp_dir + "/odrefresh";
1924*795d594fSAndroid Build Coastguard Worker 
1925*795d594fSAndroid Build Coastguard Worker   bool preparation_done = OS::FileExists(preparation_done_file.c_str());
1926*795d594fSAndroid Build Coastguard Worker 
1927*795d594fSAndroid Build Coastguard Worker   if (!preparation_done) {
1928*795d594fSAndroid Build Coastguard Worker     std::error_code ec;
1929*795d594fSAndroid Build Coastguard Worker     bool is_empty = std::filesystem::is_empty(tmp_dir, ec);
1930*795d594fSAndroid Build Coastguard Worker     if (ec) {
1931*795d594fSAndroid Build Coastguard Worker       return NonFatal(ART_FORMAT("Failed to check dir '{}': {}", tmp_dir, ec.message()));
1932*795d594fSAndroid Build Coastguard Worker     }
1933*795d594fSAndroid Build Coastguard Worker     if (!is_empty) {
1934*795d594fSAndroid Build Coastguard Worker       return Fatal(
1935*795d594fSAndroid Build Coastguard Worker           "preRebootInit must not be concurrently called or retried after cancellation or failure");
1936*795d594fSAndroid Build Coastguard Worker     }
1937*795d594fSAndroid Build Coastguard Worker   }
1938*795d594fSAndroid Build Coastguard Worker 
1939*795d594fSAndroid Build Coastguard Worker   OR_RETURN_NON_FATAL(PreRebootInitClearEnvs());
1940*795d594fSAndroid Build Coastguard Worker   OR_RETURN_NON_FATAL(
1941*795d594fSAndroid Build Coastguard Worker       PreRebootInitSetEnvFromFile(init_environ_rc_path_.value_or("/init.environ.rc")));
1942*795d594fSAndroid Build Coastguard Worker   if (!preparation_done) {
1943*795d594fSAndroid Build Coastguard Worker     OR_RETURN_NON_FATAL(PreRebootInitDeriveClasspath(classpath_file));
1944*795d594fSAndroid Build Coastguard Worker   }
1945*795d594fSAndroid Build Coastguard Worker   OR_RETURN_NON_FATAL(PreRebootInitSetEnvFromFile(classpath_file));
1946*795d594fSAndroid Build Coastguard Worker   if (!preparation_done) {
1947*795d594fSAndroid Build Coastguard Worker     OR_RETURN_NON_FATAL(BindMountNewDir(art_apex_data_dir, GetArtApexData()));
1948*795d594fSAndroid Build Coastguard Worker     OR_RETURN_NON_FATAL(BindMountNewDir(odrefresh_dir, "/data/misc/odrefresh"));
1949*795d594fSAndroid Build Coastguard Worker     ArtdCancellationSignal* cancellation_signal =
1950*795d594fSAndroid Build Coastguard Worker         OR_RETURN_FATAL(ToArtdCancellationSignal(in_cancellationSignal.get()));
1951*795d594fSAndroid Build Coastguard Worker     if (!OR_RETURN_NON_FATAL(PreRebootInitBootImages(cancellation_signal))) {
1952*795d594fSAndroid Build Coastguard Worker       *_aidl_return = false;
1953*795d594fSAndroid Build Coastguard Worker       return ScopedAStatus::ok();
1954*795d594fSAndroid Build Coastguard Worker     }
1955*795d594fSAndroid Build Coastguard Worker   }
1956*795d594fSAndroid Build Coastguard Worker 
1957*795d594fSAndroid Build Coastguard Worker   if (!preparation_done) {
1958*795d594fSAndroid Build Coastguard Worker     if (!WriteStringToFile(/*content=*/"", preparation_done_file)) {
1959*795d594fSAndroid Build Coastguard Worker       return NonFatal(
1960*795d594fSAndroid Build Coastguard Worker           ART_FORMAT("Failed to write '{}': {}", preparation_done_file, strerror(errno)));
1961*795d594fSAndroid Build Coastguard Worker     }
1962*795d594fSAndroid Build Coastguard Worker   }
1963*795d594fSAndroid Build Coastguard Worker 
1964*795d594fSAndroid Build Coastguard Worker   *_aidl_return = true;
1965*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
1966*795d594fSAndroid Build Coastguard Worker }
1967*795d594fSAndroid Build Coastguard Worker 
PreRebootInitClearEnvs()1968*795d594fSAndroid Build Coastguard Worker Result<void> Artd::PreRebootInitClearEnvs() {
1969*795d594fSAndroid Build Coastguard Worker   if (clearenv() != 0) {
1970*795d594fSAndroid Build Coastguard Worker     return ErrnoErrorf("Failed to clear environment variables");
1971*795d594fSAndroid Build Coastguard Worker   }
1972*795d594fSAndroid Build Coastguard Worker   return {};
1973*795d594fSAndroid Build Coastguard Worker }
1974*795d594fSAndroid Build Coastguard Worker 
PreRebootInitSetEnvFromFile(const std::string & path)1975*795d594fSAndroid Build Coastguard Worker Result<void> Artd::PreRebootInitSetEnvFromFile(const std::string& path) {
1976*795d594fSAndroid Build Coastguard Worker   std::regex export_line_pattern("\\s*export\\s+(.+?)\\s+(.+)");
1977*795d594fSAndroid Build Coastguard Worker 
1978*795d594fSAndroid Build Coastguard Worker   std::string content;
1979*795d594fSAndroid Build Coastguard Worker   if (!ReadFileToString(path, &content)) {
1980*795d594fSAndroid Build Coastguard Worker     return ErrnoErrorf("Failed to read '{}'", path);
1981*795d594fSAndroid Build Coastguard Worker   }
1982*795d594fSAndroid Build Coastguard Worker   bool found = false;
1983*795d594fSAndroid Build Coastguard Worker   for (const std::string& line : Split(content, "\n")) {
1984*795d594fSAndroid Build Coastguard Worker     if (line.find_first_of("\\\"") != std::string::npos) {
1985*795d594fSAndroid Build Coastguard Worker       return Errorf("Backslashes and quotes in env var file are not supported for now, got '{}'",
1986*795d594fSAndroid Build Coastguard Worker                     line);
1987*795d594fSAndroid Build Coastguard Worker     }
1988*795d594fSAndroid Build Coastguard Worker     std::smatch match;
1989*795d594fSAndroid Build Coastguard Worker     if (!std::regex_match(line, match, export_line_pattern)) {
1990*795d594fSAndroid Build Coastguard Worker       continue;
1991*795d594fSAndroid Build Coastguard Worker     }
1992*795d594fSAndroid Build Coastguard Worker     const std::string& key = match[1].str();
1993*795d594fSAndroid Build Coastguard Worker     const std::string& value = match[2].str();
1994*795d594fSAndroid Build Coastguard Worker     LOG(INFO) << ART_FORMAT("Setting environment variable '{}' to '{}'", key, value);
1995*795d594fSAndroid Build Coastguard Worker     if (setenv(key.c_str(), value.c_str(), /*replace=*/1) != 0) {
1996*795d594fSAndroid Build Coastguard Worker       return ErrnoErrorf("Failed to set environment variable '{}' to '{}'", key, value);
1997*795d594fSAndroid Build Coastguard Worker     }
1998*795d594fSAndroid Build Coastguard Worker     found = true;
1999*795d594fSAndroid Build Coastguard Worker   }
2000*795d594fSAndroid Build Coastguard Worker   if (!found) {
2001*795d594fSAndroid Build Coastguard Worker     return Errorf("Malformed env var file '{}': {}", path, content);
2002*795d594fSAndroid Build Coastguard Worker   }
2003*795d594fSAndroid Build Coastguard Worker   return {};
2004*795d594fSAndroid Build Coastguard Worker }
2005*795d594fSAndroid Build Coastguard Worker 
PreRebootInitDeriveClasspath(const std::string & path)2006*795d594fSAndroid Build Coastguard Worker Result<void> Artd::PreRebootInitDeriveClasspath(const std::string& path) {
2007*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<File> output(OS::CreateEmptyFile(path.c_str()));
2008*795d594fSAndroid Build Coastguard Worker   if (output == nullptr) {
2009*795d594fSAndroid Build Coastguard Worker     return ErrnoErrorf("Failed to create '{}'", path);
2010*795d594fSAndroid Build Coastguard Worker   }
2011*795d594fSAndroid Build Coastguard Worker 
2012*795d594fSAndroid Build Coastguard Worker   CmdlineBuilder args = OR_RETURN(GetArtExecCmdlineBuilder());
2013*795d594fSAndroid Build Coastguard Worker   args.Add("--keep-fds=%d", output->Fd())
2014*795d594fSAndroid Build Coastguard Worker       .Add("--")
2015*795d594fSAndroid Build Coastguard Worker       .Add("/apex/com.android.sdkext/bin/derive_classpath")
2016*795d594fSAndroid Build Coastguard Worker       .Add("/proc/self/fd/%d", output->Fd());
2017*795d594fSAndroid Build Coastguard Worker 
2018*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << "Running derive_classpath: " << Join(args.Get(), /*separator=*/" ");
2019*795d594fSAndroid Build Coastguard Worker 
2020*795d594fSAndroid Build Coastguard Worker   Result<int> result = ExecAndReturnCode(args.Get(), kShortTimeoutSec);
2021*795d594fSAndroid Build Coastguard Worker   if (!result.ok()) {
2022*795d594fSAndroid Build Coastguard Worker     return Errorf("Failed to run derive_classpath: {}", result.error().message());
2023*795d594fSAndroid Build Coastguard Worker   }
2024*795d594fSAndroid Build Coastguard Worker 
2025*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << ART_FORMAT("derive_classpath returned code {}", result.value());
2026*795d594fSAndroid Build Coastguard Worker 
2027*795d594fSAndroid Build Coastguard Worker   if (result.value() != 0) {
2028*795d594fSAndroid Build Coastguard Worker     return Errorf("derive_classpath returned an unexpected code: {}", result.value());
2029*795d594fSAndroid Build Coastguard Worker   }
2030*795d594fSAndroid Build Coastguard Worker 
2031*795d594fSAndroid Build Coastguard Worker   if (output->FlushClose() != 0) {
2032*795d594fSAndroid Build Coastguard Worker     return ErrnoErrorf("Failed to flush and close '{}'", path);
2033*795d594fSAndroid Build Coastguard Worker   }
2034*795d594fSAndroid Build Coastguard Worker 
2035*795d594fSAndroid Build Coastguard Worker   return {};
2036*795d594fSAndroid Build Coastguard Worker }
2037*795d594fSAndroid Build Coastguard Worker 
PreRebootInitBootImages(ArtdCancellationSignal * cancellation_signal)2038*795d594fSAndroid Build Coastguard Worker Result<bool> Artd::PreRebootInitBootImages(ArtdCancellationSignal* cancellation_signal) {
2039*795d594fSAndroid Build Coastguard Worker   CmdlineBuilder args = OR_RETURN(GetArtExecCmdlineBuilder());
2040*795d594fSAndroid Build Coastguard Worker   args.Add("--")
2041*795d594fSAndroid Build Coastguard Worker       .Add(OR_RETURN(BuildArtBinPath("odrefresh")))
2042*795d594fSAndroid Build Coastguard Worker       .Add("--only-boot-images")
2043*795d594fSAndroid Build Coastguard Worker       .Add("--compile");
2044*795d594fSAndroid Build Coastguard Worker 
2045*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << "Running odrefresh: " << Join(args.Get(), /*separator=*/" ");
2046*795d594fSAndroid Build Coastguard Worker 
2047*795d594fSAndroid Build Coastguard Worker   Result<int> result =
2048*795d594fSAndroid Build Coastguard Worker       ExecAndReturnCode(args.Get(), kLongTimeoutSec, cancellation_signal->CreateExecCallbacks());
2049*795d594fSAndroid Build Coastguard Worker   if (!result.ok()) {
2050*795d594fSAndroid Build Coastguard Worker     if (cancellation_signal->IsCancelled()) {
2051*795d594fSAndroid Build Coastguard Worker       return false;
2052*795d594fSAndroid Build Coastguard Worker     }
2053*795d594fSAndroid Build Coastguard Worker     return Errorf("Failed to run odrefresh: {}", result.error().message());
2054*795d594fSAndroid Build Coastguard Worker   }
2055*795d594fSAndroid Build Coastguard Worker 
2056*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << ART_FORMAT("odrefresh returned code {}", result.value());
2057*795d594fSAndroid Build Coastguard Worker 
2058*795d594fSAndroid Build Coastguard Worker   if (result.value() != odrefresh::ExitCode::kCompilationSuccess &&
2059*795d594fSAndroid Build Coastguard Worker       result.value() != odrefresh::ExitCode::kOkay) {
2060*795d594fSAndroid Build Coastguard Worker     return Errorf("odrefresh returned an unexpected code: {}", result.value());
2061*795d594fSAndroid Build Coastguard Worker   }
2062*795d594fSAndroid Build Coastguard Worker 
2063*795d594fSAndroid Build Coastguard Worker   return true;
2064*795d594fSAndroid Build Coastguard Worker }
2065*795d594fSAndroid Build Coastguard Worker 
validateDexPath(const std::string & in_dexFile,std::optional<std::string> * _aidl_return)2066*795d594fSAndroid Build Coastguard Worker ScopedAStatus Artd::validateDexPath(const std::string& in_dexFile,
2067*795d594fSAndroid Build Coastguard Worker                                     std::optional<std::string>* _aidl_return) {
2068*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_NOT_PRE_REBOOT(options_);
2069*795d594fSAndroid Build Coastguard Worker   if (Result<void> result = ValidateDexPath(in_dexFile); !result.ok()) {
2070*795d594fSAndroid Build Coastguard Worker     *_aidl_return = result.error().message();
2071*795d594fSAndroid Build Coastguard Worker   } else {
2072*795d594fSAndroid Build Coastguard Worker     *_aidl_return = std::nullopt;
2073*795d594fSAndroid Build Coastguard Worker   }
2074*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
2075*795d594fSAndroid Build Coastguard Worker }
2076*795d594fSAndroid Build Coastguard Worker 
validateClassLoaderContext(const std::string & in_dexFile,const std::string & in_classLoaderContext,std::optional<std::string> * _aidl_return)2077*795d594fSAndroid Build Coastguard Worker ScopedAStatus Artd::validateClassLoaderContext(const std::string& in_dexFile,
2078*795d594fSAndroid Build Coastguard Worker                                                const std::string& in_classLoaderContext,
2079*795d594fSAndroid Build Coastguard Worker                                                std::optional<std::string>* _aidl_return) {
2080*795d594fSAndroid Build Coastguard Worker   RETURN_FATAL_IF_NOT_PRE_REBOOT(options_);
2081*795d594fSAndroid Build Coastguard Worker   if (Result<void> result = ValidateClassLoaderContext(in_dexFile, in_classLoaderContext);
2082*795d594fSAndroid Build Coastguard Worker       !result.ok()) {
2083*795d594fSAndroid Build Coastguard Worker     *_aidl_return = result.error().message();
2084*795d594fSAndroid Build Coastguard Worker   } else {
2085*795d594fSAndroid Build Coastguard Worker     *_aidl_return = std::nullopt;
2086*795d594fSAndroid Build Coastguard Worker   }
2087*795d594fSAndroid Build Coastguard Worker   return ScopedAStatus::ok();
2088*795d594fSAndroid Build Coastguard Worker }
2089*795d594fSAndroid Build Coastguard Worker 
Create(const std::string & filename)2090*795d594fSAndroid Build Coastguard Worker Result<BuildSystemProperties> BuildSystemProperties::Create(const std::string& filename) {
2091*795d594fSAndroid Build Coastguard Worker   std::string content;
2092*795d594fSAndroid Build Coastguard Worker   if (!ReadFileToString(filename, &content)) {
2093*795d594fSAndroid Build Coastguard Worker     return ErrnoErrorf("Failed to read '{}'", filename);
2094*795d594fSAndroid Build Coastguard Worker   }
2095*795d594fSAndroid Build Coastguard Worker   std::regex import_pattern(R"re(import\s.*)re");
2096*795d594fSAndroid Build Coastguard Worker   std::unordered_map<std::string, std::string> system_properties;
2097*795d594fSAndroid Build Coastguard Worker   for (const std::string& raw_line : Split(content, "\n")) {
2098*795d594fSAndroid Build Coastguard Worker     std::string line = Trim(raw_line);
2099*795d594fSAndroid Build Coastguard Worker     if (line.empty() || line.starts_with('#') || std::regex_match(line, import_pattern)) {
2100*795d594fSAndroid Build Coastguard Worker       continue;
2101*795d594fSAndroid Build Coastguard Worker     }
2102*795d594fSAndroid Build Coastguard Worker     size_t pos = line.find('=');
2103*795d594fSAndroid Build Coastguard Worker     if (pos == std::string::npos || pos == 0 || (pos == 1 && line[1] == '?')) {
2104*795d594fSAndroid Build Coastguard Worker       return Errorf("Malformed system property line '{}' in file '{}'", line, filename);
2105*795d594fSAndroid Build Coastguard Worker     }
2106*795d594fSAndroid Build Coastguard Worker     if (line[pos - 1] == '?') {
2107*795d594fSAndroid Build Coastguard Worker       std::string key = line.substr(/*pos=*/0, /*n=*/pos - 1);
2108*795d594fSAndroid Build Coastguard Worker       if (system_properties.find(key) == system_properties.end()) {
2109*795d594fSAndroid Build Coastguard Worker         system_properties[key] = line.substr(pos + 1);
2110*795d594fSAndroid Build Coastguard Worker       }
2111*795d594fSAndroid Build Coastguard Worker     } else {
2112*795d594fSAndroid Build Coastguard Worker       system_properties[line.substr(/*pos=*/0, /*n=*/pos)] = line.substr(pos + 1);
2113*795d594fSAndroid Build Coastguard Worker     }
2114*795d594fSAndroid Build Coastguard Worker   }
2115*795d594fSAndroid Build Coastguard Worker   return BuildSystemProperties(std::move(system_properties));
2116*795d594fSAndroid Build Coastguard Worker }
2117*795d594fSAndroid Build Coastguard Worker 
GetProperty(const std::string & key) const2118*795d594fSAndroid Build Coastguard Worker std::string BuildSystemProperties::GetProperty(const std::string& key) const {
2119*795d594fSAndroid Build Coastguard Worker   auto it = system_properties_.find(key);
2120*795d594fSAndroid Build Coastguard Worker   return it != system_properties_.end() ? it->second : "";
2121*795d594fSAndroid Build Coastguard Worker }
2122*795d594fSAndroid Build Coastguard Worker 
2123*795d594fSAndroid Build Coastguard Worker }  // namespace artd
2124*795d594fSAndroid Build Coastguard Worker }  // namespace art
2125