1 /**
2 * Copyright (c) 2020, 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 #define LOG_TAG "carwatchdogd"
18
19 #include "PackageInfoResolver.h"
20
21 #include <android-base/strings.h>
22 #include <android/automotive/watchdog/internal/ApplicationCategoryType.h>
23 #include <android/automotive/watchdog/internal/ComponentType.h>
24 #include <android/automotive/watchdog/internal/UidType.h>
25 #include <cutils/android_filesystem_config.h>
26
27 #include <inttypes.h>
28
29 #include <iterator>
30 #include <string_view>
31
32 namespace android {
33 namespace automotive {
34 namespace watchdog {
35
36 using ::android::IBinder;
37 using ::android::sp;
38 using ::android::automotive::watchdog::internal::ApplicationCategoryType;
39 using ::android::automotive::watchdog::internal::ComponentType;
40 using ::android::automotive::watchdog::internal::PackageInfo;
41 using ::android::automotive::watchdog::internal::UidType;
42 using ::android::base::Error;
43 using ::android::base::Result;
44 using ::android::base::StartsWith;
45 using ::android::binder::Status;
46
47 using GetpwuidFunction = std::function<struct passwd*(uid_t)>;
48 using PackageToAppCategoryMap =
49 std::unordered_map<std::string,
50 android::automotive::watchdog::internal::ApplicationCategoryType>;
51
52 namespace {
53
54 constexpr const char* kSharedPackagePrefix = "shared:";
55
getComponentTypeForNativeUid(uid_t uid,std::string_view packageName,const std::vector<std::string> & vendorPackagePrefixes)56 ComponentType getComponentTypeForNativeUid(uid_t uid, std::string_view packageName,
57 const std::vector<std::string>& vendorPackagePrefixes) {
58 for (const auto& prefix : vendorPackagePrefixes) {
59 if (StartsWith(packageName, prefix)) {
60 return ComponentType::VENDOR;
61 }
62 }
63 if ((uid >= AID_OEM_RESERVED_START && uid <= AID_OEM_RESERVED_END) ||
64 (uid >= AID_OEM_RESERVED_2_START && uid <= AID_OEM_RESERVED_2_END) ||
65 (uid >= AID_ODM_RESERVED_START && uid <= AID_ODM_RESERVED_END)) {
66 return ComponentType::VENDOR;
67 }
68 /**
69 * There are no third party native services. Thus all non-vendor services are considered system
70 * services.
71 */
72 return ComponentType::SYSTEM;
73 }
74
getPackageInfoForNativeUid(uid_t uid,const std::vector<std::string> & vendorPackagePrefixes,const GetpwuidFunction & getpwuidHandler)75 Result<PackageInfo> getPackageInfoForNativeUid(
76 uid_t uid, const std::vector<std::string>& vendorPackagePrefixes,
77 const GetpwuidFunction& getpwuidHandler) {
78 PackageInfo packageInfo;
79 passwd* usrpwd = getpwuidHandler(uid);
80 if (!usrpwd) {
81 return Error() << "Failed to fetch package name";
82 }
83 const char* packageName = usrpwd->pw_name;
84 packageInfo.packageIdentifier.name = packageName;
85 packageInfo.packageIdentifier.uid = uid;
86 packageInfo.uidType = UidType::NATIVE;
87 packageInfo.componentType =
88 getComponentTypeForNativeUid(uid, packageName, vendorPackagePrefixes);
89 packageInfo.appCategoryType = ApplicationCategoryType::OTHERS;
90 packageInfo.sharedUidPackages = {};
91
92 return packageInfo;
93 }
94
95 } // namespace
96
97 sp<PackageInfoResolver> PackageInfoResolver::sInstance = nullptr;
98 GetpwuidFunction PackageInfoResolver::sGetpwuidHandler = &getpwuid;
99
getInstance()100 sp<IPackageInfoResolver> PackageInfoResolver::getInstance() {
101 if (sInstance == nullptr) {
102 sInstance = new PackageInfoResolver();
103 }
104 return sInstance;
105 }
106
terminate()107 void PackageInfoResolver::terminate() {
108 sInstance.clear();
109 }
110
initWatchdogServiceHelper(const sp<IWatchdogServiceHelper> & watchdogServiceHelper)111 Result<void> PackageInfoResolver::initWatchdogServiceHelper(
112 const sp<IWatchdogServiceHelper>& watchdogServiceHelper) {
113 std::unique_lock writeLock(mRWMutex);
114 if (watchdogServiceHelper == nullptr) {
115 return Error() << "Must provide a non-null watchdog service helper instance";
116 }
117 if (mWatchdogServiceHelper != nullptr) {
118 return Error() << "Duplicate initialization";
119 }
120 mWatchdogServiceHelper = watchdogServiceHelper;
121 return {};
122 }
123
setPackageConfigurations(const std::unordered_set<std::string> & vendorPackagePrefixes,const PackageToAppCategoryMap & packagesToAppCategories)124 void PackageInfoResolver::setPackageConfigurations(
125 const std::unordered_set<std::string>& vendorPackagePrefixes,
126 const PackageToAppCategoryMap& packagesToAppCategories) {
127 std::unique_lock writeLock(mRWMutex);
128 mVendorPackagePrefixes.clear();
129 std::copy(vendorPackagePrefixes.begin(), vendorPackagePrefixes.end(),
130 std::back_inserter(mVendorPackagePrefixes));
131 mPackagesToAppCategories = packagesToAppCategories;
132 // Clear the package info cache as the package configurations have changed.
133 mUidToPackageInfoMapping.clear();
134 }
135
updatePackageInfos(const std::vector<uid_t> & uids)136 void PackageInfoResolver::updatePackageInfos(const std::vector<uid_t>& uids) {
137 std::unique_lock writeLock(mRWMutex);
138 std::vector<int32_t> missingUids;
139 for (const uid_t uid : uids) {
140 if (mUidToPackageInfoMapping.find(uid) != mUidToPackageInfoMapping.end()) {
141 continue;
142 }
143 if (uid >= AID_APP_START) {
144 missingUids.emplace_back(static_cast<int32_t>(uid));
145 continue;
146 }
147 auto result = getPackageInfoForNativeUid(uid, mVendorPackagePrefixes,
148 PackageInfoResolver::sGetpwuidHandler);
149 if (!result.ok()) {
150 missingUids.emplace_back(static_cast<int32_t>(uid));
151 continue;
152 }
153 mUidToPackageInfoMapping[uid] = *result;
154 if (StartsWith(result->packageIdentifier.name, kSharedPackagePrefix)) {
155 // When the UID is shared, poll car watchdog service to fetch the shared packages info.
156 missingUids.emplace_back(static_cast<int32_t>(uid));
157 }
158 }
159
160 /*
161 * There is delay between creating package manager instance and initializing watchdog service
162 * helper. Thus check the watchdog service helper instance before proceeding further.
163 */
164 if (missingUids.empty() || mWatchdogServiceHelper == nullptr) {
165 return;
166 }
167
168 std::vector<PackageInfo> packageInfos;
169 Status status =
170 mWatchdogServiceHelper->getPackageInfosForUids(missingUids, mVendorPackagePrefixes,
171 &packageInfos);
172 if (!status.isOk()) {
173 ALOGE("Failed to fetch package infos from car watchdog service: %s",
174 status.exceptionMessage().c_str());
175 return;
176 }
177 for (auto& packageInfo : packageInfos) {
178 const auto& id = packageInfo.packageIdentifier;
179 if (id.name.empty()) {
180 continue;
181 }
182 if (const auto it = mPackagesToAppCategories.find(id.name);
183 packageInfo.uidType == UidType::APPLICATION && it != mPackagesToAppCategories.end()) {
184 packageInfo.appCategoryType = it->second;
185 }
186 mUidToPackageInfoMapping[id.uid] = packageInfo;
187 }
188 }
189
getPackageNamesForUids(const std::vector<uid_t> & uids)190 std::unordered_map<uid_t, std::string> PackageInfoResolver::getPackageNamesForUids(
191 const std::vector<uid_t>& uids) {
192 std::unordered_map<uid_t, std::string> uidToPackageNameMapping;
193 if (uids.empty()) {
194 return uidToPackageNameMapping;
195 }
196 updatePackageInfos(uids);
197 {
198 std::shared_lock readLock(mRWMutex);
199 for (const auto& uid : uids) {
200 if (mUidToPackageInfoMapping.find(uid) != mUidToPackageInfoMapping.end()) {
201 uidToPackageNameMapping[uid] =
202 mUidToPackageInfoMapping.at(uid).packageIdentifier.name;
203 }
204 }
205 }
206 return uidToPackageNameMapping;
207 }
208
getPackageInfosForUids(const std::vector<uid_t> & uids)209 std::unordered_map<uid_t, PackageInfo> PackageInfoResolver::getPackageInfosForUids(
210 const std::vector<uid_t>& uids) {
211 std::unordered_map<uid_t, PackageInfo> uidToPackageInfoMapping;
212 if (uids.empty()) {
213 return uidToPackageInfoMapping;
214 }
215 updatePackageInfos(uids);
216 {
217 std::shared_lock readLock(mRWMutex);
218 for (const auto& uid : uids) {
219 if (mUidToPackageInfoMapping.find(uid) != mUidToPackageInfoMapping.end()) {
220 uidToPackageInfoMapping[uid] = mUidToPackageInfoMapping.at(uid);
221 }
222 }
223 }
224 return uidToPackageInfoMapping;
225 }
226
227 } // namespace watchdog
228 } // namespace automotive
229 } // namespace android
230