xref: /aosp_15_r20/art/artd/path_utils.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "path_utils.h"
18 
19 #include <filesystem>
20 #include <string>
21 #include <vector>
22 
23 #include "aidl/com/android/server/art/ArtConstants.h"
24 #include "aidl/com/android/server/art/BnArtd.h"
25 #include "android-base/errors.h"
26 #include "android-base/result.h"
27 #include "arch/instruction_set.h"
28 #include "base/file_utils.h"
29 #include "base/macros.h"
30 #include "file_utils.h"
31 #include "oat/oat_file_assistant.h"
32 #include "runtime_image.h"
33 #include "service.h"
34 #include "tools/tools.h"
35 
36 namespace art {
37 namespace artd {
38 
39 namespace {
40 
41 using ::aidl::com::android::server::art::ArtConstants;
42 using ::aidl::com::android::server::art::ArtifactsPath;
43 using ::aidl::com::android::server::art::DexMetadataPath;
44 using ::aidl::com::android::server::art::OutputArtifacts;
45 using ::aidl::com::android::server::art::OutputProfile;
46 using ::aidl::com::android::server::art::ProfilePath;
47 using ::aidl::com::android::server::art::RuntimeArtifactsPath;
48 using ::aidl::com::android::server::art::VdexPath;
49 using ::android::base::Error;
50 using ::android::base::Result;
51 using ::art::service::ValidateDexPath;
52 using ::art::service::ValidatePathElement;
53 using ::art::service::ValidatePathElementSubstring;
54 
55 using PrebuiltProfilePath = ProfilePath::PrebuiltProfilePath;
56 using PrimaryCurProfilePath = ProfilePath::PrimaryCurProfilePath;
57 using PrimaryRefProfilePath = ProfilePath::PrimaryRefProfilePath;
58 using SecondaryCurProfilePath = ProfilePath::SecondaryCurProfilePath;
59 using SecondaryRefProfilePath = ProfilePath::SecondaryRefProfilePath;
60 using TmpProfilePath = ProfilePath::TmpProfilePath;
61 using WritableProfilePath = ProfilePath::WritableProfilePath;
62 
63 constexpr const char* kPreRebootSuffix = ".staged";
64 
65 // Only to be changed for testing.
66 std::string_view gListRootDir = "/";
67 
68 }  // namespace
69 
GetAndroidDataOrError()70 Result<std::string> GetAndroidDataOrError() {
71   std::string error_msg;
72   std::string result = GetAndroidDataSafe(&error_msg);
73   if (!error_msg.empty()) {
74     return Error() << error_msg;
75   }
76   return result;
77 }
78 
GetAndroidExpandOrError()79 Result<std::string> GetAndroidExpandOrError() {
80   std::string error_msg;
81   std::string result = GetAndroidExpandSafe(&error_msg);
82   if (!error_msg.empty()) {
83     return Error() << error_msg;
84   }
85   return result;
86 }
87 
GetArtRootOrError()88 Result<std::string> GetArtRootOrError() {
89   std::string error_msg;
90   std::string result = GetArtRootSafe(&error_msg);
91   if (!error_msg.empty()) {
92     return Error() << error_msg;
93   }
94   return result;
95 }
96 
ListManagedFiles(const std::string & android_data,const std::string & android_expand)97 std::vector<std::string> ListManagedFiles(const std::string& android_data,
98                                           const std::string& android_expand) {
99   // See `art::tools::Glob` for the syntax.
100   std::vector<std::string> patterns = {
101       // Profiles for primary dex files.
102       android_data + "/misc/profiles/**",
103       // Artifacts for primary dex files.
104       android_data + "/dalvik-cache/**",
105   };
106 
107   for (const std::string& data_root : {android_data, android_expand + "/*"}) {
108     // Artifacts for primary dex files.
109     patterns.push_back(data_root + "/app/*/*/oat/**");
110 
111     for (const char* user_dir : {"/user", "/user_de"}) {
112       std::string data_dir = data_root + user_dir + "/*/*";
113       // Profiles and artifacts for secondary dex files. Those files are in app data directories, so
114       // we use more granular patterns to avoid accidentally deleting apps' files.
115       std::string secondary_oat_dir = data_dir + "/**/oat";
116       for (const char* suffix : {"", ".*.tmp", kPreRebootSuffix}) {
117         patterns.push_back(secondary_oat_dir + "/*" + ArtConstants::PROFILE_FILE_EXT + suffix);
118         patterns.push_back(secondary_oat_dir + "/*/*" + kOdexExtension + suffix);
119         patterns.push_back(secondary_oat_dir + "/*/*" + kVdexExtension + suffix);
120         patterns.push_back(secondary_oat_dir + "/*/*" + kArtExtension + suffix);
121       }
122       // Runtime image files.
123       patterns.push_back(RuntimeImage::GetRuntimeImageDir(data_dir) + "**");
124     }
125   }
126 
127   return tools::Glob(patterns, gListRootDir);
128 }
129 
ListRuntimeArtifactsFiles(const std::string & android_data,const std::string & android_expand,const RuntimeArtifactsPath & runtime_artifacts_path)130 std::vector<std::string> ListRuntimeArtifactsFiles(
131     const std::string& android_data,
132     const std::string& android_expand,
133     const RuntimeArtifactsPath& runtime_artifacts_path) {
134   // See `art::tools::Glob` for the syntax.
135   std::vector<std::string> patterns;
136 
137   for (const std::string& data_root : {android_data, android_expand + "/*"}) {
138     for (const char* user_dir : {"/user", "/user_de"}) {
139       std::string data_dir =
140           data_root + user_dir + "/*/" + tools::EscapeGlob(runtime_artifacts_path.packageName);
141       patterns.push_back(
142           RuntimeImage::GetRuntimeImagePath(data_dir,
143                                             tools::EscapeGlob(runtime_artifacts_path.dexPath),
144                                             tools::EscapeGlob(runtime_artifacts_path.isa)));
145     }
146   }
147 
148   return tools::Glob(patterns, gListRootDir);
149 }
150 
ValidateRuntimeArtifactsPath(const RuntimeArtifactsPath & runtime_artifacts_path)151 Result<void> ValidateRuntimeArtifactsPath(const RuntimeArtifactsPath& runtime_artifacts_path) {
152   OR_RETURN(ValidatePathElement(runtime_artifacts_path.packageName, "packageName"));
153   OR_RETURN(ValidatePathElement(runtime_artifacts_path.isa, "isa"));
154   OR_RETURN(ValidateDexPath(runtime_artifacts_path.dexPath));
155   return {};
156 }
157 
BuildArtBinPath(const std::string & binary_name)158 Result<std::string> BuildArtBinPath(const std::string& binary_name) {
159   return ART_FORMAT("{}/bin/{}", OR_RETURN(GetArtRootOrError()), binary_name);
160 }
161 
BuildArtifactsPath(const ArtifactsPath & artifacts_path)162 Result<RawArtifactsPath> BuildArtifactsPath(const ArtifactsPath& artifacts_path) {
163   OR_RETURN(ValidateDexPath(artifacts_path.dexPath));
164 
165   InstructionSet isa = GetInstructionSetFromString(artifacts_path.isa.c_str());
166   if (isa == InstructionSet::kNone) {
167     return Errorf("Instruction set '{}' is invalid", artifacts_path.isa);
168   }
169 
170   std::string error_msg;
171   RawArtifactsPath path;
172   if (artifacts_path.isInDalvikCache) {
173     // Apps' OAT files are never in ART APEX data.
174     if (!OatFileAssistant::DexLocationToOatFilename(artifacts_path.dexPath,
175                                                     isa,
176                                                     /*deny_art_apex_data_files=*/true,
177                                                     &path.oat_path,
178                                                     &error_msg)) {
179       return Error() << error_msg;
180     }
181   } else {
182     if (!OatFileAssistant::DexLocationToOdexFilename(
183             artifacts_path.dexPath, isa, &path.oat_path, &error_msg)) {
184       return Error() << error_msg;
185     }
186   }
187 
188   path.vdex_path = ReplaceFileExtension(path.oat_path, kVdexExtension);
189   path.art_path = ReplaceFileExtension(path.oat_path, kArtExtension);
190 
191   if (artifacts_path.isPreReboot) {
192     path.oat_path += kPreRebootSuffix;
193     path.vdex_path += kPreRebootSuffix;
194     path.art_path += kPreRebootSuffix;
195   }
196 
197   return path;
198 }
199 
BuildPrimaryRefProfilePath(const PrimaryRefProfilePath & primary_ref_profile_path)200 Result<std::string> BuildPrimaryRefProfilePath(
201     const PrimaryRefProfilePath& primary_ref_profile_path) {
202   OR_RETURN(ValidatePathElement(primary_ref_profile_path.packageName, "packageName"));
203   OR_RETURN(ValidatePathElementSubstring(primary_ref_profile_path.profileName, "profileName"));
204   return ART_FORMAT("{}/misc/profiles/ref/{}/{}{}{}",
205                     OR_RETURN(GetAndroidDataOrError()),
206                     primary_ref_profile_path.packageName,
207                     primary_ref_profile_path.profileName,
208                     ArtConstants::PROFILE_FILE_EXT,
209                     primary_ref_profile_path.isPreReboot ? kPreRebootSuffix : "");
210 }
211 
BuildPrebuiltProfilePath(const PrebuiltProfilePath & prebuilt_profile_path)212 Result<std::string> BuildPrebuiltProfilePath(const PrebuiltProfilePath& prebuilt_profile_path) {
213   OR_RETURN(ValidateDexPath(prebuilt_profile_path.dexPath));
214   return prebuilt_profile_path.dexPath + ArtConstants::PROFILE_FILE_EXT;
215 }
216 
BuildPrimaryCurProfilePath(const PrimaryCurProfilePath & primary_cur_profile_path)217 Result<std::string> BuildPrimaryCurProfilePath(
218     const PrimaryCurProfilePath& primary_cur_profile_path) {
219   OR_RETURN(ValidatePathElement(primary_cur_profile_path.packageName, "packageName"));
220   OR_RETURN(ValidatePathElementSubstring(primary_cur_profile_path.profileName, "profileName"));
221   return ART_FORMAT("{}/misc/profiles/cur/{}/{}/{}{}",
222                     OR_RETURN(GetAndroidDataOrError()),
223                     primary_cur_profile_path.userId,
224                     primary_cur_profile_path.packageName,
225                     primary_cur_profile_path.profileName,
226                     ArtConstants::PROFILE_FILE_EXT);
227 }
228 
BuildSecondaryRefProfilePath(const SecondaryRefProfilePath & secondary_ref_profile_path)229 Result<std::string> BuildSecondaryRefProfilePath(
230     const SecondaryRefProfilePath& secondary_ref_profile_path) {
231   OR_RETURN(ValidateDexPath(secondary_ref_profile_path.dexPath));
232   std::filesystem::path dex_path(secondary_ref_profile_path.dexPath);
233   return ART_FORMAT("{}/oat/{}{}{}",
234                     dex_path.parent_path().string(),
235                     dex_path.filename().string(),
236                     ArtConstants::PROFILE_FILE_EXT,
237                     secondary_ref_profile_path.isPreReboot ? kPreRebootSuffix : "");
238 }
239 
BuildSecondaryCurProfilePath(const SecondaryCurProfilePath & secondary_cur_profile_path)240 Result<std::string> BuildSecondaryCurProfilePath(
241     const SecondaryCurProfilePath& secondary_cur_profile_path) {
242   OR_RETURN(ValidateDexPath(secondary_cur_profile_path.dexPath));
243   std::filesystem::path dex_path(secondary_cur_profile_path.dexPath);
244   return ART_FORMAT("{}/oat/{}.cur{}",
245                     dex_path.parent_path().string(),
246                     dex_path.filename().string(),
247                     ArtConstants::PROFILE_FILE_EXT);
248 }
249 
BuildWritableProfilePath(const WritableProfilePath & profile_path)250 Result<std::string> BuildWritableProfilePath(const WritableProfilePath& profile_path) {
251   switch (profile_path.getTag()) {
252     case WritableProfilePath::forPrimary:
253       return BuildPrimaryRefProfilePath(profile_path.get<WritableProfilePath::forPrimary>());
254     case WritableProfilePath::forSecondary:
255       return BuildSecondaryRefProfilePath(profile_path.get<WritableProfilePath::forSecondary>());
256       // No default. All cases should be explicitly handled, or the compilation will fail.
257   }
258   // This should never happen. Just in case we get a non-enumerator value.
259   LOG(FATAL) << ART_FORMAT("Unexpected writable profile path type {}",
260                            fmt::underlying(profile_path.getTag()));
261 }
262 
BuildFinalProfilePath(const TmpProfilePath & tmp_profile_path)263 Result<std::string> BuildFinalProfilePath(const TmpProfilePath& tmp_profile_path) {
264   return BuildWritableProfilePath(tmp_profile_path.finalPath);
265 }
266 
BuildTmpProfilePath(const TmpProfilePath & tmp_profile_path)267 Result<std::string> BuildTmpProfilePath(const TmpProfilePath& tmp_profile_path) {
268   OR_RETURN(ValidatePathElementSubstring(tmp_profile_path.id, "id"));
269   return NewFile::BuildTempPath(OR_RETURN(BuildFinalProfilePath(tmp_profile_path)),
270                                 tmp_profile_path.id);
271 }
272 
BuildDexMetadataPath(const DexMetadataPath & dex_metadata_path)273 Result<std::string> BuildDexMetadataPath(const DexMetadataPath& dex_metadata_path) {
274   OR_RETURN(ValidateDexPath(dex_metadata_path.dexPath));
275   return ReplaceFileExtension(dex_metadata_path.dexPath, kDmExtension);
276 }
277 
BuildProfileOrDmPath(const ProfilePath & profile_path)278 Result<std::string> BuildProfileOrDmPath(const ProfilePath& profile_path) {
279   switch (profile_path.getTag()) {
280     case ProfilePath::primaryRefProfilePath:
281       return BuildPrimaryRefProfilePath(profile_path.get<ProfilePath::primaryRefProfilePath>());
282     case ProfilePath::prebuiltProfilePath:
283       return BuildPrebuiltProfilePath(profile_path.get<ProfilePath::prebuiltProfilePath>());
284     case ProfilePath::primaryCurProfilePath:
285       return BuildPrimaryCurProfilePath(profile_path.get<ProfilePath::primaryCurProfilePath>());
286     case ProfilePath::secondaryRefProfilePath:
287       return BuildSecondaryRefProfilePath(profile_path.get<ProfilePath::secondaryRefProfilePath>());
288     case ProfilePath::secondaryCurProfilePath:
289       return BuildSecondaryCurProfilePath(profile_path.get<ProfilePath::secondaryCurProfilePath>());
290     case ProfilePath::tmpProfilePath:
291       return BuildTmpProfilePath(profile_path.get<ProfilePath::tmpProfilePath>());
292     case ProfilePath::dexMetadataPath:
293       return BuildDexMetadataPath(profile_path.get<ProfilePath::dexMetadataPath>());
294       // No default. All cases should be explicitly handled, or the compilation will fail.
295   }
296   // This should never happen. Just in case we get a non-enumerator value.
297   LOG(FATAL) << ART_FORMAT("Unexpected profile path type {}",
298                            fmt::underlying(profile_path.getTag()));
299 }
300 
BuildVdexPath(const VdexPath & vdex_path)301 Result<std::string> BuildVdexPath(const VdexPath& vdex_path) {
302   DCHECK(vdex_path.getTag() == VdexPath::artifactsPath);
303   return OR_RETURN(BuildArtifactsPath(vdex_path.get<VdexPath::artifactsPath>())).vdex_path;
304 }
305 
PreRebootFlag(const ProfilePath & profile_path)306 bool PreRebootFlag(const ProfilePath& profile_path) {
307   switch (profile_path.getTag()) {
308     case ProfilePath::primaryRefProfilePath:
309       return profile_path.get<ProfilePath::primaryRefProfilePath>().isPreReboot;
310     case ProfilePath::secondaryRefProfilePath:
311       return profile_path.get<ProfilePath::secondaryRefProfilePath>().isPreReboot;
312     case ProfilePath::tmpProfilePath:
313       return PreRebootFlag(profile_path.get<ProfilePath::tmpProfilePath>());
314     case ProfilePath::prebuiltProfilePath:
315     case ProfilePath::primaryCurProfilePath:
316     case ProfilePath::secondaryCurProfilePath:
317     case ProfilePath::dexMetadataPath:
318       return false;
319       // No default. All cases should be explicitly handled, or the compilation will fail.
320   }
321   // This should never happen. Just in case we get a non-enumerator value.
322   LOG(FATAL) << ART_FORMAT("Unexpected profile path type {}",
323                            fmt::underlying(profile_path.getTag()));
324 }
325 
PreRebootFlag(const TmpProfilePath & tmp_profile_path)326 bool PreRebootFlag(const TmpProfilePath& tmp_profile_path) {
327   return PreRebootFlag(tmp_profile_path.finalPath);
328 }
329 
PreRebootFlag(const OutputProfile & profile)330 bool PreRebootFlag(const OutputProfile& profile) { return PreRebootFlag(profile.profilePath); }
331 
PreRebootFlag(const ArtifactsPath & artifacts_path)332 bool PreRebootFlag(const ArtifactsPath& artifacts_path) { return artifacts_path.isPreReboot; }
333 
PreRebootFlag(const OutputArtifacts & artifacts)334 bool PreRebootFlag(const OutputArtifacts& artifacts) {
335   return PreRebootFlag(artifacts.artifactsPath);
336 }
337 
PreRebootFlag(const VdexPath & vdex_path)338 bool PreRebootFlag(const VdexPath& vdex_path) {
339   return PreRebootFlag(vdex_path.get<VdexPath::artifactsPath>());
340 }
341 
IsPreRebootStagedFile(std::string_view filename)342 bool IsPreRebootStagedFile(std::string_view filename) {
343   return filename.ends_with(kPreRebootSuffix);
344 }
345 
TestOnlySetListRootDir(std::string_view root_dir)346 void TestOnlySetListRootDir(std::string_view root_dir) { gListRootDir = root_dir; }
347 
348 }  // namespace artd
349 }  // namespace art
350