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_RUNTIME_APP_INFO_H_
18 #define ART_RUNTIME_APP_INFO_H_
19 
20 #include <vector>
21 
22 #include "base/macros.h"
23 #include "base/mutex.h"
24 #include <base/safe_map.h>
25 
26 namespace art HIDDEN {
27 
28 // Constants used by VMRuntime.java to interface with the runtime.
29 // We could get them from the well known class but it's simpler to
30 // redefine them here.
31 
32 // VMRuntime.CODE_PATH_TYPE_PRIMARY_APK
33 static constexpr int32_t kVMRuntimePrimaryApk = 1 << 0;
34 // VMRuntime.CODE_PATH_TYPE_SPLIT_APK
35 static constexpr int32_t kVMRuntimeSplitApk = 1 << 1;
36 // VMRuntime.CODE_PATH_TYPE_SECONDARY_DEX
37 static constexpr int32_t kVMRuntimeSecondaryDex = 1 << 2;
38 
39 // Encapsulates the information the runtime has about the application.
40 //
41 // The app's info comes from 2 channels:
42 //   1) during class loading, when we load oat files.
43 //   2) during app startup, when the framework calls VMRuntime#registerAppInfo.
44 // In general the class loading event happens before VMRuntime#registerAppInfo.
45 class AppInfo {
46  public:
47   enum class CodeType {
48     kUnknown,
49     kPrimaryApk,
50     kSplitApk,
51     kSecondaryDex,
52   };
53 
54   // Converts VMRuntime.java constansts to a CodeType.
55   static CodeType FromVMRuntimeConstants(uint32_t code_type);
56 
57   AppInfo();
58 
59   // Registers the application code paths, types, and associated profiles.
60   void RegisterAppInfo(const std::string& package_name,
61                        const std::vector<std::string>& code_paths,
62                        const std::string& profile_output_filename,
63                        const std::string& ref_profile_filename,
64                        CodeType code_type);
65 
66   // Registers the optimization status for single code path.
67   void RegisterOdexStatus(const std::string& code_path,
68                           const std::string& compiler_filter,
69                           const std::string& compilation_reason,
70                           const std::string& odex_status);
71 
72   // Extracts the optimization status of the primary APK into the given arguments.
73   // If there are multiple primary APKs registed via RegisterAppInfo, the method
74   // will assign the status of the first APK, sorted by the location name.
75   //
76   // Assigns "unknown" if there is no primary APK or the optimization status was
77   // not set via RegisterOdexStatus,
78   void GetPrimaryApkOptimizationStatus(std::string* out_compiler_filter,
79                                        std::string* out_compilation_reason);
80 
81   // Returns the reference profile path of the primary APK.
82   // If there are multiple primary APKs registed via RegisterAppInfo, the method
83   // will return the profile of the first APK, sorted by the location name.
84   //
85   // Returns an empty string if there is no primary APK.
86   std::string GetPrimaryApkReferenceProfile();
87 
88   // Returns the path of the primary APK.
89   // If there are multiple primary APKs registed via RegisterAppInfo, the method
90   // will return the path of the first APK, sorted by the location name.
91   //
92   // Returns an empty string if there is no primary APK.
93   std::string GetPrimaryApkPath();
94 
95   // Whether we've received a call to RegisterAppInfo.
96   bool HasRegisteredAppInfo();
97 
98   // The registered code type for a given code path. Note that this will
99   // be kUnknown until an explicit registration for that path has been made.
100   CodeType GetRegisteredCodeType(const std::string& code_path);
101 
102  private:
103   // Encapsulates optimization information about a particular code location.
104   struct CodeLocationInfo {
105     // The type of the code location (primary, split, secondary, unknown).
106     CodeType code_type{CodeType::kUnknown};
107 
108     // The compiler filter of the oat file. Note that this contains
109     // the output of OatFileAssistant#GetOptimizationStatus() which may
110     // contain values outside the scope of the CompilerFilter enum.
111     std::optional<std::string> compiler_filter;
112 
113     // The compiler reason of the oat file. Note that this contains
114     // the output of OatFileAssistant#GetOptimizationStatus().
115     std::optional<std::string> compilation_reason;
116 
117     // The odes status as produced by OatFileAssistant#GetOptimizationStatus().
118     std::optional<std::string> odex_status;
119 
120     // The path to the primary profile if given.
121     std::optional<std::string> cur_profile_path;
122 
123     // The path to the reference profile if given.
124     std::optional<std::string> ref_profile_path;
125   };
126 
127   // The name of the package if set.
128   std::optional<std::string> package_name_ GUARDED_BY(update_mutex_);
129 
130   // The registered code locations.
131   SafeMap<std::string, CodeLocationInfo> registered_code_locations_ GUARDED_BY(update_mutex_);
132 
133   // Lock to touch the state ot the AppInfo object.
134   art::Mutex update_mutex_ BOTTOM_MUTEX_ACQUIRED_AFTER;
135 
136   friend std::ostream& operator<<(std::ostream& os, AppInfo& rhs);
137 };
138 
139 std::ostream& operator<<(std::ostream& os, AppInfo& rhs);
140 
141 }  // namespace art
142 
143 #endif  // ART_RUNTIME_APP_INFO_H_
144