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 #include <app_info.h>
18
19 #include "base/logging.h"
20 #include "base/mutex.h"
21 #include "base/safe_map.h"
22 #include "thread-inl.h"
23
24 namespace art {
25
26 static constexpr const char* kUnknownValue = "unknown";
27
AppInfo()28 AppInfo::AppInfo()
29 : update_mutex_("app_info_update_mutex", LockLevel::kGenericBottomLock) {}
30
31 // Converts VMRuntime.java constansts to a CodeType.
FromVMRuntimeConstants(uint32_t code_type)32 AppInfo::CodeType AppInfo::FromVMRuntimeConstants(uint32_t code_type) {
33 switch (code_type) {
34 case kVMRuntimePrimaryApk : return CodeType::kPrimaryApk;
35 case kVMRuntimeSplitApk : return CodeType::kPrimaryApk;
36 case kVMRuntimeSecondaryDex : return CodeType::kSecondaryDex;
37 default:
38 LOG(WARNING) << "Unknown code type: " << code_type;
39 return CodeType::kUnknown;
40 }
41 }
42
CodeTypeName(AppInfo::CodeType code_type)43 static const char* CodeTypeName(AppInfo::CodeType code_type) {
44 switch (code_type) {
45 case AppInfo::CodeType::kPrimaryApk : return "primary-apk";
46 case AppInfo::CodeType::kSplitApk : return "split-apk";
47 case AppInfo::CodeType::kSecondaryDex : return "secondary-dex";
48 case AppInfo::CodeType::kUnknown : return "unknown";
49 }
50 }
51
RegisterAppInfo(const std::string & package_name,const std::vector<std::string> & code_paths,const std::string & cur_profile_path,const std::string & ref_profile_path,AppInfo::CodeType code_type)52 void AppInfo::RegisterAppInfo(const std::string& package_name,
53 const std::vector<std::string>& code_paths,
54 const std::string& cur_profile_path,
55 const std::string& ref_profile_path,
56 AppInfo::CodeType code_type) {
57 MutexLock mu(Thread::Current(), update_mutex_);
58
59 package_name_ = package_name;
60
61 for (const std::string& code_path : code_paths) {
62 CodeLocationInfo& cli = registered_code_locations_.GetOrCreate(
63 code_path, []() { return CodeLocationInfo(); });
64 cli.cur_profile_path = cur_profile_path;
65 cli.ref_profile_path = ref_profile_path;
66 cli.code_type = code_type;
67
68 VLOG(startup) << "Registering code path. "
69 << "\npackage_name=" << package_name
70 << "\ncode_path=" << code_path
71 << "\ncode_type=" << CodeTypeName(code_type)
72 << "\ncur_profile=" << cur_profile_path
73 << "\nref_profile=" << ref_profile_path;
74 }
75 }
76
RegisterOdexStatus(const std::string & code_path,const std::string & compiler_filter,const std::string & compilation_reason,const std::string & odex_status)77 void AppInfo::RegisterOdexStatus(const std::string& code_path,
78 const std::string& compiler_filter,
79 const std::string& compilation_reason,
80 const std::string& odex_status) {
81 MutexLock mu(Thread::Current(), update_mutex_);
82
83 CodeLocationInfo& cli = registered_code_locations_.GetOrCreate(
84 code_path, []() { return CodeLocationInfo(); });
85 cli.compiler_filter = compiler_filter;
86 cli.compilation_reason = compilation_reason;
87 cli.odex_status = odex_status;
88
89 VLOG(startup) << "Registering odex status. "
90 << "\ncode_path=" << code_path
91 << "\ncompiler_filter=" << compiler_filter
92 << "\ncompilation_reason=" << compilation_reason
93 << "\nodex_status=" << odex_status;
94 }
95
HasRegisteredAppInfo()96 bool AppInfo::HasRegisteredAppInfo() {
97 MutexLock mu(Thread::Current(), update_mutex_);
98
99 return package_name_.has_value();
100 }
101
GetPrimaryApkOptimizationStatus(std::string * out_compiler_filter,std::string * out_compilation_reason)102 void AppInfo::GetPrimaryApkOptimizationStatus(
103 std::string* out_compiler_filter,
104 std::string* out_compilation_reason) {
105 MutexLock mu(Thread::Current(), update_mutex_);
106
107 for (const auto& it : registered_code_locations_) {
108 const CodeLocationInfo& cli = it.second;
109 if (cli.code_type == CodeType::kPrimaryApk) {
110 *out_compiler_filter = cli.compiler_filter.value_or(kUnknownValue);
111 *out_compilation_reason = cli.compilation_reason.value_or(kUnknownValue);
112 return;
113 }
114 }
115 *out_compiler_filter = kUnknownValue;
116 *out_compilation_reason = kUnknownValue;
117 }
118
GetRegisteredCodeType(const std::string & code_path)119 AppInfo::CodeType AppInfo::GetRegisteredCodeType(const std::string& code_path) {
120 MutexLock mu(Thread::Current(), update_mutex_);
121
122 const auto it = registered_code_locations_.find(code_path);
123 return it != registered_code_locations_.end() ? it->second.code_type : CodeType::kUnknown;
124 }
125
operator <<(std::ostream & os,AppInfo & rhs)126 std::ostream& operator<<(std::ostream& os, AppInfo& rhs) {
127 MutexLock mu(Thread::Current(), rhs.update_mutex_);
128
129 os << "AppInfo for package_name=" << rhs.package_name_.value_or(kUnknownValue) << "\n";
130 for (const auto& it : rhs.registered_code_locations_) {
131 const std::string code_path = it.first;
132 const AppInfo::CodeLocationInfo& cli = it.second;
133
134 os << "\ncode_path=" << code_path
135 << "\ncode_type=" << CodeTypeName(cli.code_type)
136 << "\ncompiler_filter=" << cli.compiler_filter.value_or(kUnknownValue)
137 << "\ncompilation_reason=" << cli.compilation_reason.value_or(kUnknownValue)
138 << "\nodex_status=" << cli.odex_status.value_or(kUnknownValue)
139 << "\ncur_profile=" << cli.cur_profile_path.value_or(kUnknownValue)
140 << "\nref_profile=" << cli.ref_profile_path.value_or(kUnknownValue)
141 << "\n";
142 }
143 return os;
144 }
145
GetPrimaryApkReferenceProfile()146 std::string AppInfo::GetPrimaryApkReferenceProfile() {
147 MutexLock mu(Thread::Current(), update_mutex_);
148
149 for (const auto& it : registered_code_locations_) {
150 const CodeLocationInfo& cli = it.second;
151 if (cli.code_type == CodeType::kPrimaryApk) {
152 return cli.ref_profile_path.value_or("");
153 }
154 }
155 return "";
156 }
157
158
159 } // namespace art
160