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