xref: /aosp_15_r20/art/odrefresh/odrefresh.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1 /*
2  * Copyright (C) 2021 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 #ifndef ART_ODREFRESH_ODREFRESH_H_
18 #define ART_ODREFRESH_ODREFRESH_H_
19 
20 #include <ctime>
21 #include <functional>
22 #include <memory>
23 #include <optional>
24 #include <set>
25 #include <string>
26 #include <unordered_set>
27 #include <vector>
28 
29 #include "android-base/function_ref.h"
30 #include "android-base/result.h"
31 #include "base/os.h"
32 #include "com_android_apex.h"
33 #include "com_android_art.h"
34 #include "exec_utils.h"
35 #include "odr_artifacts.h"
36 #include "odr_config.h"
37 #include "odr_metrics.h"
38 #include "odrefresh/odrefresh.h"
39 #include "tools/cmdline_builder.h"
40 
41 namespace art {
42 namespace odrefresh {
43 
44 class OnDeviceRefresh;
45 
46 struct BootImages {
47   static constexpr int kMaxCount = 2;
48 
49   bool primary_boot_image : 1;
50   bool boot_image_mainline_extension : 1;
51 
52   int Count() const;
53 
54   OdrMetrics::BcpCompilationType GetTypeForMetrics() const;
55 };
56 
57 struct CompilationOptions {
58   // If not empty, generate the boot images for ISAs in the list.
59   std::vector<std::pair<InstructionSet, BootImages>> boot_images_to_generate_for_isas;
60 
61   // If not empty, compile the system server jars in the list.
62   std::set<std::string> system_server_jars_to_compile;
63 
64   static CompilationOptions CompileAll(const OnDeviceRefresh& odr);
65 
66   int CompilationUnitCount() const;
67 };
68 
69 struct CompilationResult {
70   OdrMetrics::Status status = OdrMetrics::Status::kOK;
71   std::string error_msg;
72   int64_t elapsed_time_ms = 0;
73   std::optional<ExecResult> dex2oat_result;
74 
OkCompilationResult75   static CompilationResult Ok() { return {}; }
76 
Dex2oatOkCompilationResult77   static CompilationResult Dex2oatOk(int64_t elapsed_time_ms, const ExecResult& dex2oat_result) {
78     return {.elapsed_time_ms = elapsed_time_ms, .dex2oat_result = dex2oat_result};
79   }
80 
ErrorCompilationResult81   static CompilationResult Error(OdrMetrics::Status status, const std::string& error_msg) {
82     return {.status = status, .error_msg = error_msg};
83   }
84 
Dex2oatErrorCompilationResult85   static CompilationResult Dex2oatError(const std::string& error_msg,
86                                         int64_t elapsed_time_ms,
87                                         const ExecResult& dex2oat_result) {
88     return {.status = OdrMetrics::Status::kDex2OatError,
89             .error_msg = error_msg,
90             .elapsed_time_ms = elapsed_time_ms,
91             .dex2oat_result = dex2oat_result};
92   }
93 
IsOkCompilationResult94   bool IsOk() { return status == OdrMetrics::Status::kOK; }
95 
MergeCompilationResult96   void Merge(const CompilationResult& other) {
97     // Accumulate the compilation time.
98     elapsed_time_ms += other.elapsed_time_ms;
99 
100     // Only keep the first failure.
101     if (status == OdrMetrics::Status::kOK) {
102       status = other.status;
103       error_msg = other.error_msg;
104       dex2oat_result = other.dex2oat_result;
105     }
106   }
107 };
108 
109 class PreconditionCheckResult {
110  public:
NoneOk(OdrMetrics::Trigger trigger)111   static PreconditionCheckResult NoneOk(OdrMetrics::Trigger trigger) {
112     return PreconditionCheckResult(trigger,
113                                    /*primary_boot_image_ok=*/false,
114                                    /*boot_image_mainline_extension_ok=*/false,
115                                    /*system_server_ok=*/false);
116   }
BootImageMainlineExtensionNotOk(OdrMetrics::Trigger trigger)117   static PreconditionCheckResult BootImageMainlineExtensionNotOk(OdrMetrics::Trigger trigger) {
118     return PreconditionCheckResult(trigger,
119                                    /*primary_boot_image_ok=*/true,
120                                    /*boot_image_mainline_extension_ok=*/false,
121                                    /*system_server_ok=*/false);
122   }
SystemServerNotOk(OdrMetrics::Trigger trigger)123   static PreconditionCheckResult SystemServerNotOk(OdrMetrics::Trigger trigger) {
124     return PreconditionCheckResult(trigger,
125                                    /*primary_boot_image_ok=*/true,
126                                    /*boot_image_mainline_extension_ok=*/true,
127                                    /*system_server_ok=*/false);
128   }
AllOk()129   static PreconditionCheckResult AllOk() {
130     return PreconditionCheckResult(/*trigger=*/std::nullopt,
131                                    /*primary_boot_image_ok=*/true,
132                                    /*boot_image_mainline_extension_ok=*/true,
133                                    /*system_server_ok=*/true);
134   }
IsAllOk()135   bool IsAllOk() const { return !trigger_.has_value(); }
GetTrigger()136   OdrMetrics::Trigger GetTrigger() const { return trigger_.value(); }
IsPrimaryBootImageOk()137   bool IsPrimaryBootImageOk() const { return primary_boot_image_ok_; }
IsBootImageMainlineExtensionOk()138   bool IsBootImageMainlineExtensionOk() const { return boot_image_mainline_extension_ok_; }
IsSystemServerOk()139   bool IsSystemServerOk() const { return system_server_ok_; }
140 
141  private:
142   // Use static factory methods instead.
PreconditionCheckResult(std::optional<OdrMetrics::Trigger> trigger,bool primary_boot_image_ok,bool boot_image_mainline_extension_ok,bool system_server_ok)143   PreconditionCheckResult(std::optional<OdrMetrics::Trigger> trigger,
144                           bool primary_boot_image_ok,
145                           bool boot_image_mainline_extension_ok,
146                           bool system_server_ok)
147       : trigger_(trigger),
148         primary_boot_image_ok_(primary_boot_image_ok),
149         boot_image_mainline_extension_ok_(boot_image_mainline_extension_ok),
150         system_server_ok_(system_server_ok) {}
151 
152   // Indicates why the precondition is not okay, or `std::nullopt` if it's okay.
153   std::optional<OdrMetrics::Trigger> trigger_;
154   bool primary_boot_image_ok_;
155   bool boot_image_mainline_extension_ok_;
156   bool system_server_ok_;
157 };
158 
159 class OnDeviceRefresh final {
160  public:
161   explicit OnDeviceRefresh(
162       const OdrConfig& config,
163       android::base::function_ref<int(const char*, const char*)> setfilecon,
164       android::base::function_ref<int(const char*, unsigned int)> restorecon);
165 
166   // Constructor with injections. For testing and internal use only.
167   OnDeviceRefresh(
168       const OdrConfig& config,
169       android::base::function_ref<int(const char*, const char*)> setfilecon,
170       android::base::function_ref<int(const char*, unsigned int)> restorecon,
171       const std::string& cache_info_filename,
172       std::unique_ptr<ExecUtils> exec_utils,
173       android::base::function_ref<bool()> check_compilation_space);
174 
175   // Returns the exit code and specifies what should be compiled in `compilation_options`.
176   WARN_UNUSED ExitCode
177   CheckArtifactsAreUpToDate(OdrMetrics& metrics,
178                             /*out*/ CompilationOptions* compilation_options) const;
179 
180   WARN_UNUSED ExitCode Compile(OdrMetrics& metrics, CompilationOptions compilation_options) const;
181 
182   WARN_UNUSED bool RemoveArtifactsDirectory() const;
183 
184   // Returns a set of all system server jars.
AllSystemServerJars()185   std::set<std::string> AllSystemServerJars() const {
186     return {all_systemserver_jars_.begin(), all_systemserver_jars_.end()};
187   }
188 
Config()189   const OdrConfig& Config() const { return config_; }
190 
191  private:
192   time_t GetExecutionTimeUsed() const;
193 
194   time_t GetExecutionTimeRemaining() const;
195 
196   time_t GetSubprocessTimeout() const;
197 
198   android::base::Result<std::string> CreateStagingDirectory() const;
199 
200   // Gets the `ApexInfo` for active APEXes.
201   std::optional<std::vector<com::android::apex::ApexInfo>> GetApexInfoList() const;
202 
203   // Reads the ART APEX cache information (if any) found in the output artifact directory.
204   android::base::Result<com::android::art::CacheInfo> ReadCacheInfo() const;
205 
206   // Writes ART APEX cache information to `kOnDeviceRefreshOdrefreshArtifactDirectory`.
207   android::base::Result<void> WriteCacheInfo() const;
208 
209   std::vector<com::android::art::Component> GenerateBootClasspathComponents() const;
210 
211   std::vector<com::android::art::Component> GenerateDex2oatBootClasspathComponents() const;
212 
213   std::vector<com::android::art::SystemServerComponent> GenerateSystemServerComponents() const;
214 
215   // Returns the list of BCP jars in the ART module.
216   std::vector<std::string> GetArtBcpJars() const;
217 
218   // Returns the list of BCP jars for the boot image framework extension.
219   std::vector<std::string> GetFrameworkBcpJars() const;
220 
221   // Returns the list of BCP jars for the boot image mainline extension.
222   std::vector<std::string> GetMainlineBcpJars() const;
223 
224   // Returns the symbolic primary boot image location (without ISA). If `minimal` is true, returns
225   // the symbolic location of the minimal boot image.
226   std::string GetPrimaryBootImage(bool on_system, bool minimal) const;
227 
228   // Returns the real primary boot image location (with ISA).  If `minimal` is true, returns the
229   // real location of the minimal boot image.
230   std::string GetPrimaryBootImagePath(bool on_system, bool minimal, InstructionSet isa) const;
231 
232   // Returns the symbolic boot image framework extension location (without ISA). Note that this only
233   // applies to boot images on /system.
234   std::string GetSystemBootImageFrameworkExtension() const;
235 
236   // Returns the real boot image framework extension location (with ISA). Note that this only
237   // applies to boot images on /system.
238   std::string GetSystemBootImageFrameworkExtensionPath(InstructionSet isa) const;
239 
240   // Returns the symbolic boot image mainline extension location (without ISA).
241   std::string GetBootImageMainlineExtension(bool on_system) const;
242 
243   // Returns the real boot image mainline extension location (with ISA).
244   std::string GetBootImageMainlineExtensionPath(bool on_system, InstructionSet isa) const;
245 
246   // Returns the best combination of symbolic boot image locations (without ISA) based on file
247   // existence.
248   std::vector<std::string> GetBestBootImages(InstructionSet isa,
249                                              bool include_mainline_extension) const;
250 
251   std::string GetSystemServerImagePath(bool on_system, const std::string& jar_path) const;
252 
253   // Removes files that are not in the list.
254   android::base::Result<void> CleanupArtifactDirectory(
255       OdrMetrics& metrics, const std::vector<std::string>& artifacts_to_keep) const;
256 
257   // Loads artifacts to memory and writes them back. This is a workaround for old versions of
258   // odsign, which encounters "file exists" error when it adds existing artifacts to fs-verity. This
259   // function essentially removes existing artifacts from fs-verity to avoid the error.
260   android::base::Result<void> RefreshExistingArtifacts() const;
261 
262   // Returns whether the primary boot image is present.
263   // If `on_system` is true, checks both the primary boot image and the framework extension on
264   // /system.
265   // If `minimal` is true, checks the minimal boot image.
266   // If `checked_artifacts` is present, adds checked artifacts to `checked_artifacts`.
267   WARN_UNUSED bool PrimaryBootImageExist(
268       bool on_system,
269       bool minimal,
270       InstructionSet isa,
271       /*out*/ std::string* error_msg,
272       /*out*/ std::vector<std::string>* checked_artifacts = nullptr) const;
273 
274   // Returns whether the boot image mainline extension exists.
275   WARN_UNUSED bool BootImageMainlineExtensionExist(
276       bool on_system,
277       InstructionSet isa,
278       /*out*/ std::string* error_msg,
279       /*out*/ std::vector<std::string>* checked_artifacts = nullptr) const;
280 
281   // Checks whether all system_server artifacts are present. The artifacts are checked in their
282   // order of compilation. Returns true if all are present, false otherwise.
283   // Adds the paths to the jars that are missing artifacts in `jars_with_missing_artifacts`.
284   // If `checked_artifacts` is present, adds checked artifacts to `checked_artifacts`.
285   bool SystemServerArtifactsExist(
286       bool on_system,
287       /*out*/ std::string* error_msg,
288       /*out*/ std::set<std::string>* jars_missing_artifacts,
289       /*out*/ std::vector<std::string>* checked_artifacts = nullptr) const;
290 
291   // Returns true if all of the system properties listed in `kSystemProperties` are set to the
292   // default values. This function is usually called when cache-info.xml does not exist (i.e.,
293   // compilation has not been done before).
294   WARN_UNUSED bool CheckSystemPropertiesAreDefault() const;
295 
296   // Returns true if none of the system properties listed in `kSystemProperties` has changed since
297   // the last compilation. This function is usually called when cache-info.xml exists.
298   WARN_UNUSED bool CheckSystemPropertiesHaveNotChanged(
299       const com::android::art::CacheInfo& cache_info) const;
300 
301   // Returns true if the system image is built with the right userfaultfd GC flag.
302   WARN_UNUSED bool CheckBuildUserfaultFdGc() const;
303 
304   // Returns whether the precondition for using artifacts on /system is met. Note that this function
305   // does not check the artifacts.
306   WARN_UNUSED PreconditionCheckResult
307   CheckPreconditionForSystem(const std::vector<com::android::apex::ApexInfo>& apex_info_list) const;
308 
309   // Returns whether the precondition for using artifacts on /data is met. Note that this function
310   // does not check the artifacts.
311   WARN_UNUSED PreconditionCheckResult
312   CheckPreconditionForData(const std::vector<com::android::apex::ApexInfo>& apex_info_list) const;
313 
314   // Checks whether all boot classpath artifacts are up to date. Returns the boot images that need
315   // to be (re-)generated. If `checked_artifacts` is present, adds checked artifacts to
316   // `checked_artifacts`.
317   WARN_UNUSED BootImages
318   CheckBootClasspathArtifactsAreUpToDate(OdrMetrics& metrics,
319                                          InstructionSet isa,
320                                          const PreconditionCheckResult& system_result,
321                                          const PreconditionCheckResult& data_result,
322                                          /*out*/ std::vector<std::string>* checked_artifacts) const;
323 
324   // Checks whether all system_server artifacts are up to date. The artifacts are checked in their
325   // order of compilation. Returns the paths to the jars that need to be compiled.
326   // If `checked_artifacts` is present, adds checked artifacts to `checked_artifacts`.
327   WARN_UNUSED std::set<std::string> CheckSystemServerArtifactsAreUpToDate(
328       OdrMetrics& metrics,
329       const PreconditionCheckResult& system_result,
330       const PreconditionCheckResult& data_result,
331       /*out*/ std::vector<std::string>* checked_artifacts) const;
332 
333   WARN_UNUSED CompilationResult
334   RunDex2oat(const std::string& staging_dir,
335              const std::string& debug_message,
336              InstructionSet isa,
337              const std::vector<std::string>& dex_files,
338              const std::vector<std::string>& boot_classpath,
339              const std::vector<std::string>& input_boot_images,
340              const OdrArtifacts& artifacts,
341              tools::CmdlineBuilder&& extra_args,
342              /*inout*/ std::vector<std::unique_ptr<File>>& readonly_files_raii) const;
343 
344   WARN_UNUSED CompilationResult
345   RunDex2oatForBootClasspath(const std::string& staging_dir,
346                              const std::string& debug_name,
347                              InstructionSet isa,
348                              const std::vector<std::string>& dex_files,
349                              const std::vector<std::string>& boot_classpath,
350                              const std::vector<std::string>& input_boot_images,
351                              const std::string& output_path) const;
352 
353   WARN_UNUSED CompilationResult
354   CompileBootClasspath(const std::string& staging_dir,
355                        InstructionSet isa,
356                        BootImages boot_images,
357                        const std::function<void()>& on_dex2oat_success) const;
358 
359   WARN_UNUSED CompilationResult
360   RunDex2oatForSystemServer(const std::string& staging_dir,
361                             const std::string& dex_file,
362                             const std::vector<std::string>& classloader_context) const;
363 
364   WARN_UNUSED CompilationResult
365   CompileSystemServer(const std::string& staging_dir,
366                       const std::set<std::string>& system_server_jars_to_compile,
367                       const std::function<void()>& on_dex2oat_success) const;
368 
369   // Configuration to use.
370   const OdrConfig& config_;
371 
372   // Path to cache information file that is used to speed up artifact checking.
373   const std::string cache_info_filename_;
374 
375   // The raw list from DEX2OATBOOTCLASSPATH. This is the list of jars that should be compiled into
376   // the primary boot image.
377   std::vector<std::string> dex2oat_boot_classpath_jars_;
378 
379   // The raw list from BOOTCLASSPATH. This is the list of all BCP jars.
380   std::vector<std::string> boot_classpath_jars_;
381 
382   // Set of system_server components in SYSTEMSERVERCLASSPATH that should be compiled.
383   std::unordered_set<std::string> systemserver_classpath_jars_;
384 
385   // List of all system_server components, including those in SYSTEMSERVERCLASSPATH and those in
386   // STANDALONE_SYSTEMSERVER_JARS (jars that system_server loads dynamically using separate
387   // classloaders).
388   std::vector<std::string> all_systemserver_jars_;
389 
390   const time_t start_time_;
391 
392   std::unique_ptr<ExecUtils> exec_utils_;
393 
394   android::base::function_ref<bool()> check_compilation_space_;
395   android::base::function_ref<int(const char*, const char*)> setfilecon_;
396   android::base::function_ref<int(const char*, unsigned int)> restorecon_;
397 
398   DISALLOW_COPY_AND_ASSIGN(OnDeviceRefresh);
399 };
400 
401 }  // namespace odrefresh
402 }  // namespace art
403 
404 #endif  // ART_ODREFRESH_ODREFRESH_H_
405