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