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(const OdrConfig& config);
162 
163   // Constructor with injections. For testing and internal use only.
164   OnDeviceRefresh(const OdrConfig& config,
165                   const std::string& cache_info_filename,
166                   std::unique_ptr<ExecUtils> exec_utils,
167                   android::base::function_ref<bool()> check_compilation_space,
168                   android::base::function_ref<int(const char*, const char*)> setfilecon);
169 
170   // Returns the exit code and specifies what should be compiled in `compilation_options`.
171   WARN_UNUSED ExitCode
172   CheckArtifactsAreUpToDate(OdrMetrics& metrics,
173                             /*out*/ CompilationOptions* compilation_options) const;
174 
175   WARN_UNUSED ExitCode Compile(OdrMetrics& metrics, 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   android::base::Result<std::string> CreateStagingDirectory() const;
194 
195   // Gets the `ApexInfo` for active APEXes.
196   std::optional<std::vector<com::android::apex::ApexInfo>> GetApexInfoList() const;
197 
198   // Reads the ART APEX cache information (if any) found in the output artifact directory.
199   android::base::Result<com::android::art::CacheInfo> ReadCacheInfo() const;
200 
201   // Writes ART APEX cache information to `kOnDeviceRefreshOdrefreshArtifactDirectory`.
202   android::base::Result<void> WriteCacheInfo() const;
203 
204   std::vector<com::android::art::Component> GenerateBootClasspathComponents() const;
205 
206   std::vector<com::android::art::Component> GenerateDex2oatBootClasspathComponents() const;
207 
208   std::vector<com::android::art::SystemServerComponent> GenerateSystemServerComponents() const;
209 
210   // Returns the list of BCP jars in the ART module.
211   std::vector<std::string> GetArtBcpJars() const;
212 
213   // Returns the list of BCP jars for the boot image framework extension.
214   std::vector<std::string> GetFrameworkBcpJars() const;
215 
216   // Returns the list of BCP jars for the boot image mainline extension.
217   std::vector<std::string> GetMainlineBcpJars() const;
218 
219   // Returns the symbolic primary boot image location (without ISA). If `minimal` is true, returns
220   // the symbolic location of the minimal boot image.
221   std::string GetPrimaryBootImage(bool on_system, bool minimal) const;
222 
223   // Returns the real primary boot image location (with ISA).  If `minimal` is true, returns the
224   // real location of the minimal boot image.
225   std::string GetPrimaryBootImagePath(bool on_system, bool minimal, InstructionSet isa) const;
226 
227   // Returns the symbolic boot image framework extension location (without ISA). Note that this only
228   // applies to boot images on /system.
229   std::string GetSystemBootImageFrameworkExtension() const;
230 
231   // Returns the real boot image framework extension location (with ISA). Note that this only
232   // applies to boot images on /system.
233   std::string GetSystemBootImageFrameworkExtensionPath(InstructionSet isa) const;
234 
235   // Returns the symbolic boot image mainline extension location (without ISA).
236   std::string GetBootImageMainlineExtension(bool on_system) const;
237 
238   // Returns the real boot image mainline extension location (with ISA).
239   std::string GetBootImageMainlineExtensionPath(bool on_system, InstructionSet isa) const;
240 
241   // Returns the best combination of symbolic boot image locations (without ISA) based on file
242   // existence.
243   std::vector<std::string> GetBestBootImages(InstructionSet isa,
244                                              bool include_mainline_extension) const;
245 
246   std::string GetSystemServerImagePath(bool on_system, const std::string& jar_path) const;
247 
248   // Removes files that are not in the list.
249   android::base::Result<void> CleanupArtifactDirectory(
250       OdrMetrics& metrics, const std::vector<std::string>& artifacts_to_keep) const;
251 
252   // Loads artifacts to memory and writes them back. This is a workaround for old versions of
253   // odsign, which encounters "file exists" error when it adds existing artifacts to fs-verity. This
254   // function essentially removes existing artifacts from fs-verity to avoid the error.
255   android::base::Result<void> RefreshExistingArtifacts() const;
256 
257   // Returns whether the primary boot image is present.
258   // If `on_system` is true, checks both the primary boot image and the framework extension on
259   // /system.
260   // If `minimal` is true, checks the minimal boot image.
261   // If `checked_artifacts` is present, adds checked artifacts to `checked_artifacts`.
262   WARN_UNUSED bool PrimaryBootImageExist(
263       bool on_system,
264       bool minimal,
265       InstructionSet isa,
266       /*out*/ std::string* error_msg,
267       /*out*/ std::vector<std::string>* checked_artifacts = nullptr) const;
268 
269   // Returns whether the boot image mainline extension exists.
270   WARN_UNUSED bool BootImageMainlineExtensionExist(
271       bool on_system,
272       InstructionSet isa,
273       /*out*/ std::string* error_msg,
274       /*out*/ std::vector<std::string>* checked_artifacts = nullptr) const;
275 
276   // Checks whether all system_server artifacts are present. The artifacts are checked in their
277   // order of compilation. Returns true if all are present, false otherwise.
278   // Adds the paths to the jars that are missing artifacts in `jars_with_missing_artifacts`.
279   // If `checked_artifacts` is present, adds checked artifacts to `checked_artifacts`.
280   bool SystemServerArtifactsExist(
281       bool on_system,
282       /*out*/ std::string* error_msg,
283       /*out*/ std::set<std::string>* jars_missing_artifacts,
284       /*out*/ std::vector<std::string>* checked_artifacts = nullptr) const;
285 
286   // Returns true if all of the system properties listed in `kSystemProperties` are set to the
287   // default values. This function is usually called when cache-info.xml does not exist (i.e.,
288   // compilation has not been done before).
289   WARN_UNUSED bool CheckSystemPropertiesAreDefault() const;
290 
291   // Returns true if none of the system properties listed in `kSystemProperties` has changed since
292   // the last compilation. This function is usually called when cache-info.xml exists.
293   WARN_UNUSED bool CheckSystemPropertiesHaveNotChanged(
294       const com::android::art::CacheInfo& cache_info) const;
295 
296   // Returns true if the system image is built with the right userfaultfd GC flag.
297   WARN_UNUSED bool CheckBuildUserfaultFdGc() const;
298 
299   // Returns whether the precondition for using artifacts on /system is met. Note that this function
300   // does not check the artifacts.
301   WARN_UNUSED PreconditionCheckResult
302   CheckPreconditionForSystem(const std::vector<com::android::apex::ApexInfo>& apex_info_list) const;
303 
304   // Returns whether the precondition for using artifacts on /data is met. Note that this function
305   // does not check the artifacts.
306   WARN_UNUSED PreconditionCheckResult
307   CheckPreconditionForData(const std::vector<com::android::apex::ApexInfo>& apex_info_list) const;
308 
309   // Checks whether all boot classpath artifacts are up to date. Returns the boot images that need
310   // to be (re-)generated. If `checked_artifacts` is present, adds checked artifacts to
311   // `checked_artifacts`.
312   WARN_UNUSED BootImages
313   CheckBootClasspathArtifactsAreUpToDate(OdrMetrics& metrics,
314                                          InstructionSet isa,
315                                          const PreconditionCheckResult& system_result,
316                                          const PreconditionCheckResult& data_result,
317                                          /*out*/ std::vector<std::string>* checked_artifacts) const;
318 
319   // Checks whether all system_server artifacts are up to date. The artifacts are checked in their
320   // order of compilation. Returns the paths to the jars that need to be compiled.
321   // If `checked_artifacts` is present, adds checked artifacts to `checked_artifacts`.
322   WARN_UNUSED std::set<std::string> CheckSystemServerArtifactsAreUpToDate(
323       OdrMetrics& metrics,
324       const PreconditionCheckResult& system_result,
325       const PreconditionCheckResult& data_result,
326       /*out*/ std::vector<std::string>* checked_artifacts) const;
327 
328   WARN_UNUSED CompilationResult
329   RunDex2oat(const std::string& staging_dir,
330              const std::string& debug_message,
331              InstructionSet isa,
332              const std::vector<std::string>& dex_files,
333              const std::vector<std::string>& boot_classpath,
334              const std::vector<std::string>& input_boot_images,
335              const OdrArtifacts& artifacts,
336              tools::CmdlineBuilder&& extra_args,
337              /*inout*/ std::vector<std::unique_ptr<File>>& readonly_files_raii) const;
338 
339   WARN_UNUSED CompilationResult
340   RunDex2oatForBootClasspath(const std::string& staging_dir,
341                              const std::string& debug_name,
342                              InstructionSet isa,
343                              const std::vector<std::string>& dex_files,
344                              const std::vector<std::string>& boot_classpath,
345                              const std::vector<std::string>& input_boot_images,
346                              const std::string& output_path) const;
347 
348   WARN_UNUSED CompilationResult
349   CompileBootClasspath(const std::string& staging_dir,
350                        InstructionSet isa,
351                        BootImages boot_images,
352                        const std::function<void()>& on_dex2oat_success) const;
353 
354   WARN_UNUSED CompilationResult
355   RunDex2oatForSystemServer(const std::string& staging_dir,
356                             const std::string& dex_file,
357                             const std::vector<std::string>& classloader_context) const;
358 
359   WARN_UNUSED CompilationResult
360   CompileSystemServer(const std::string& staging_dir,
361                       const std::set<std::string>& system_server_jars_to_compile,
362                       const std::function<void()>& on_dex2oat_success) const;
363 
364   // Configuration to use.
365   const OdrConfig& config_;
366 
367   // Path to cache information file that is used to speed up artifact checking.
368   const std::string cache_info_filename_;
369 
370   // The raw list from DEX2OATBOOTCLASSPATH. This is the list of jars that should be compiled into
371   // the primary boot image.
372   std::vector<std::string> dex2oat_boot_classpath_jars_;
373 
374   // The raw list from BOOTCLASSPATH. This is the list of all BCP jars.
375   std::vector<std::string> boot_classpath_jars_;
376 
377   // Set of system_server components in SYSTEMSERVERCLASSPATH that should be compiled.
378   std::unordered_set<std::string> systemserver_classpath_jars_;
379 
380   // List of all system_server components, including those in SYSTEMSERVERCLASSPATH and those in
381   // STANDALONE_SYSTEMSERVER_JARS (jars that system_server loads dynamically using separate
382   // classloaders).
383   std::vector<std::string> all_systemserver_jars_;
384 
385   const time_t start_time_;
386 
387   std::unique_ptr<ExecUtils> exec_utils_;
388 
389   android::base::function_ref<bool()> check_compilation_space_;
390   android::base::function_ref<int(const char*, const char*)> setfilecon_;
391 
392   DISALLOW_COPY_AND_ASSIGN(OnDeviceRefresh);
393 };
394 
395 }  // namespace odrefresh
396 }  // namespace art
397 
398 #endif  // ART_ODREFRESH_ODREFRESH_H_
399