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
GetPrimaryApkOptimizationStatus(std::string * out_compiler_filter,std::string * out_compilation_reason)96 void AppInfo::GetPrimaryApkOptimizationStatus(
97 std::string* out_compiler_filter,
98 std::string* out_compilation_reason) {
99 MutexLock mu(Thread::Current(), update_mutex_);
100
101 for (const auto& it : registered_code_locations_) {
102 const CodeLocationInfo& cli = it.second;
103 if (cli.code_type == CodeType::kPrimaryApk) {
104 *out_compiler_filter = cli.compiler_filter.value_or(kUnknownValue);
105 *out_compilation_reason = cli.compilation_reason.value_or(kUnknownValue);
106 return;
107 }
108 }
109 *out_compiler_filter = kUnknownValue;
110 *out_compilation_reason = kUnknownValue;
111 }
112
operator <<(std::ostream & os,AppInfo & rhs)113 std::ostream& operator<<(std::ostream& os, AppInfo& rhs) {
114 MutexLock mu(Thread::Current(), rhs.update_mutex_);
115
116 os << "AppInfo for package_name=" << rhs.package_name_.value_or(kUnknownValue) << "\n";
117 for (const auto& it : rhs.registered_code_locations_) {
118 const std::string code_path = it.first;
119 const AppInfo::CodeLocationInfo& cli = it.second;
120
121 os << "\ncode_path=" << code_path
122 << "\ncode_type=" << CodeTypeName(cli.code_type)
123 << "\ncompiler_filter=" << cli.compiler_filter.value_or(kUnknownValue)
124 << "\ncompilation_reason=" << cli.compilation_reason.value_or(kUnknownValue)
125 << "\nodex_status=" << cli.odex_status.value_or(kUnknownValue)
126 << "\ncur_profile=" << cli.cur_profile_path.value_or(kUnknownValue)
127 << "\nref_profile=" << cli.ref_profile_path.value_or(kUnknownValue)
128 << "\n";
129 }
130 return os;
131 }
132
133 } // namespace art
134