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 #include <processgroup/sched_policy.h>
27
28 #include <inttypes.h>
29 #include <pthread.h>
30
31 #include <future> // NOLINT(build/c++11)
32 #include <iterator>
33 #include <string_view>
34
35 namespace android {
36 namespace automotive {
37 namespace watchdog {
38
39 using ::aidl::android::automotive::watchdog::internal::ApplicationCategoryType;
40 using ::aidl::android::automotive::watchdog::internal::ComponentType;
41 using ::aidl::android::automotive::watchdog::internal::PackageInfo;
42 using ::aidl::android::automotive::watchdog::internal::UidType;
43 using ::android::sp;
44 using ::android::base::Error;
45 using ::android::base::Result;
46 using ::android::base::StartsWith;
47
48 using GetpwuidFunction = std::function<struct passwd*(uid_t)>;
49 using PackageToAppCategoryMap = std::unordered_map<std::string, ApplicationCategoryType>;
50
51 namespace {
52
53 constexpr const char* kSharedPackagePrefix = "shared:";
54 constexpr const char* kServiceName = "PkgInfoResolver";
55
56 const int32_t MSG_RESOLVE_PACKAGE_NAME = 0;
57
getComponentTypeForNativeUid(uid_t uid,std::string_view packageName,const std::vector<std::string> & vendorPackagePrefixes)58 ComponentType getComponentTypeForNativeUid(uid_t uid, std::string_view packageName,
59 const std::vector<std::string>& vendorPackagePrefixes) {
60 for (const auto& prefix : vendorPackagePrefixes) {
61 if (StartsWith(packageName, prefix)) {
62 return ComponentType::VENDOR;
63 }
64 }
65 if ((uid >= AID_OEM_RESERVED_START && uid <= AID_OEM_RESERVED_END) ||
66 (uid >= AID_OEM_RESERVED_2_START && uid <= AID_OEM_RESERVED_2_END) ||
67 (uid >= AID_ODM_RESERVED_START && uid <= AID_ODM_RESERVED_END)) {
68 return ComponentType::VENDOR;
69 }
70 /**
71 * There are no third party native services. Thus all non-vendor services are considered system
72 * services.
73 */
74 return ComponentType::SYSTEM;
75 }
76
getPackageInfoForNativeUid(uid_t uid,const std::vector<std::string> & vendorPackagePrefixes,const GetpwuidFunction & getpwuidHandler)77 Result<PackageInfo> getPackageInfoForNativeUid(
78 uid_t uid, const std::vector<std::string>& vendorPackagePrefixes,
79 const GetpwuidFunction& getpwuidHandler) {
80 PackageInfo packageInfo;
81 passwd* usrpwd = getpwuidHandler(uid);
82 if (!usrpwd) {
83 return Error() << "Failed to fetch package name";
84 }
85 const char* packageName = usrpwd->pw_name;
86 packageInfo.packageIdentifier.name = packageName;
87 packageInfo.packageIdentifier.uid = uid;
88 packageInfo.uidType = UidType::NATIVE;
89 packageInfo.componentType =
90 getComponentTypeForNativeUid(uid, packageName, vendorPackagePrefixes);
91 packageInfo.appCategoryType = ApplicationCategoryType::OTHERS;
92 packageInfo.sharedUidPackages = {};
93
94 return packageInfo;
95 }
96
97 } // namespace
98
99 sp<PackageInfoResolver> PackageInfoResolver::sInstance = nullptr;
100 GetpwuidFunction PackageInfoResolver::sGetpwuidHandler = &getpwuid;
101
getInstance()102 sp<PackageInfoResolverInterface> PackageInfoResolver::getInstance() {
103 if (sInstance == nullptr) {
104 sInstance = sp<PackageInfoResolver>::make();
105 }
106 return sInstance;
107 }
108
terminate()109 void PackageInfoResolver::terminate() {
110 sInstance->mShouldTerminateLooper.store(true);
111 sInstance->mHandlerLooper->removeMessages(sInstance->mMessageHandler);
112 sInstance->mHandlerLooper->wake();
113 if (sInstance->mHandlerThread.joinable()) {
114 sInstance->mHandlerThread.join();
115 }
116 sInstance.clear();
117 }
118
initWatchdogServiceHelper(const sp<WatchdogServiceHelperInterface> & watchdogServiceHelper)119 Result<void> PackageInfoResolver::initWatchdogServiceHelper(
120 const sp<WatchdogServiceHelperInterface>& watchdogServiceHelper) {
121 std::unique_lock writeLock(mRWMutex);
122 if (watchdogServiceHelper == nullptr) {
123 return Error() << "Must provide a non-null watchdog service helper instance";
124 }
125 if (mWatchdogServiceHelper != nullptr) {
126 return Error() << "Duplicate initialization";
127 }
128 mWatchdogServiceHelper = watchdogServiceHelper;
129 return {};
130 }
131
setPackageConfigurations(const std::unordered_set<std::string> & vendorPackagePrefixes,const PackageToAppCategoryMap & packagesToAppCategories)132 void PackageInfoResolver::setPackageConfigurations(
133 const std::unordered_set<std::string>& vendorPackagePrefixes,
134 const PackageToAppCategoryMap& packagesToAppCategories) {
135 std::unique_lock writeLock(mRWMutex);
136 mVendorPackagePrefixes.clear();
137 std::copy(vendorPackagePrefixes.begin(), vendorPackagePrefixes.end(),
138 std::back_inserter(mVendorPackagePrefixes));
139 mPackagesToAppCategories = packagesToAppCategories;
140 // Clear the package info cache as the package configurations have changed.
141 mUidToPackageInfoMapping.clear();
142 }
143
updatePackageInfos(const std::vector<uid_t> & uids)144 void PackageInfoResolver::updatePackageInfos(const std::vector<uid_t>& uids) {
145 std::unique_lock writeLock(mRWMutex);
146 std::vector<int32_t> missingUids;
147 for (const uid_t uid : uids) {
148 if (mUidToPackageInfoMapping.find(uid) != mUidToPackageInfoMapping.end()) {
149 continue;
150 }
151 if (uid >= AID_APP_START) {
152 missingUids.emplace_back(static_cast<int32_t>(uid));
153 continue;
154 }
155 auto result = getPackageInfoForNativeUid(uid, mVendorPackagePrefixes,
156 PackageInfoResolver::sGetpwuidHandler);
157 if (!result.ok()) {
158 missingUids.emplace_back(static_cast<int32_t>(uid));
159 continue;
160 }
161 mUidToPackageInfoMapping[uid] = *result;
162 if (StartsWith(result->packageIdentifier.name, kSharedPackagePrefix)) {
163 // When the UID is shared, poll car watchdog service to fetch the shared packages info.
164 missingUids.emplace_back(static_cast<int32_t>(uid));
165 }
166 }
167
168 /*
169 * There is delay between creating package manager instance and initializing watchdog service
170 * helper. Thus check the watchdog service helper instance before proceeding further.
171 */
172 if (missingUids.empty() || mWatchdogServiceHelper == nullptr ||
173 !mWatchdogServiceHelper->isServiceConnected()) {
174 return;
175 }
176
177 std::vector<PackageInfo> packageInfos;
178 auto status =
179 mWatchdogServiceHelper->getPackageInfosForUids(missingUids, mVendorPackagePrefixes,
180 &packageInfos);
181 if (!status.isOk()) {
182 ALOGE("Failed to fetch package infos from car watchdog service: %s", status.getMessage());
183 return;
184 }
185 for (auto& packageInfo : packageInfos) {
186 const auto& id = packageInfo.packageIdentifier;
187 if (id.name.empty()) {
188 continue;
189 }
190 if (packageInfo.uidType == UidType::APPLICATION) {
191 if (const auto it = mPackagesToAppCategories.find(id.name);
192 it != mPackagesToAppCategories.end()) {
193 packageInfo.appCategoryType = it->second;
194 } else if (!packageInfo.sharedUidPackages.empty()) {
195 /* The recommendation for the OEMs is to define the application category mapping
196 * by the shared package names. However, this a fallback to catch if any mapping is
197 * defined by the individual package name.
198 */
199 for (const auto& packageName : packageInfo.sharedUidPackages) {
200 if (const auto it = mPackagesToAppCategories.find(packageName);
201 it != mPackagesToAppCategories.end()) {
202 packageInfo.appCategoryType = it->second;
203 break;
204 }
205 }
206 }
207 }
208 mUidToPackageInfoMapping[id.uid] = packageInfo;
209 }
210 }
211
asyncFetchPackageNamesForUids(const std::vector<uid_t> & uids,const std::function<void (std::unordered_map<uid_t,std::string>)> & callback)212 void PackageInfoResolver::asyncFetchPackageNamesForUids(
213 const std::vector<uid_t>& uids,
214 const std::function<void(std::unordered_map<uid_t, std::string>)>& callback) {
215 std::shared_lock writeLock(mRWMutex);
216 mPendingPackageNames.push_back(std::make_pair(uids, callback));
217
218 mHandlerLooper->removeMessages(mMessageHandler, MSG_RESOLVE_PACKAGE_NAME);
219 mHandlerLooper->sendMessage(mMessageHandler, Message(MSG_RESOLVE_PACKAGE_NAME));
220 }
221
getPackageInfosForUids(const std::vector<uid_t> & uids)222 std::unordered_map<uid_t, PackageInfo> PackageInfoResolver::getPackageInfosForUids(
223 const std::vector<uid_t>& uids) {
224 std::unordered_map<uid_t, PackageInfo> uidToPackageInfoMapping;
225 if (uids.empty()) {
226 return uidToPackageInfoMapping;
227 }
228 updatePackageInfos(uids);
229 {
230 std::shared_lock readLock(mRWMutex);
231 for (const auto& uid : uids) {
232 if (mUidToPackageInfoMapping.find(uid) != mUidToPackageInfoMapping.end()) {
233 uidToPackageInfoMapping[uid] = mUidToPackageInfoMapping.at(uid);
234 }
235 }
236 }
237 return uidToPackageInfoMapping;
238 }
239
resolvePackageName()240 void PackageInfoResolver::resolvePackageName() {
241 std::vector<std::pair<std::vector<uid_t>,
242 std::function<void(std::unordered_map<uid_t, std::string>)>>>
243 uidsToCallbacks;
244 {
245 std::shared_lock writeLock(mRWMutex);
246 swap(mPendingPackageNames, uidsToCallbacks);
247 }
248
249 std::vector<uid_t> allUids;
250 for (const auto& uidsToCallback : uidsToCallbacks) {
251 auto uids = uidsToCallback.first;
252 allUids.insert(allUids.end(), uids.begin(), uids.end());
253 }
254 updatePackageInfos(allUids);
255
256 for (const auto& uidsToCallback : uidsToCallbacks) {
257 auto uids = uidsToCallback.first;
258 auto callback = uidsToCallback.second;
259 std::unordered_map<uid_t, std::string> uidToPackageNameMapping;
260 if (uids.empty()) {
261 callback(uidToPackageNameMapping);
262 continue;
263 }
264 for (const auto& uid : uids) {
265 std::shared_lock readLock(mRWMutex);
266 if (mUidToPackageInfoMapping.find(uid) != mUidToPackageInfoMapping.end()) {
267 uidToPackageNameMapping[uid] =
268 mUidToPackageInfoMapping.at(uid).packageIdentifier.name;
269 }
270 }
271 callback(uidToPackageNameMapping);
272 }
273 }
274
startLooper()275 void PackageInfoResolver::startLooper() {
276 auto promise = std::promise<void>();
277 auto checkLooperSet = promise.get_future();
278 mHandlerThread = std::thread([&]() {
279 mHandlerLooper->setLooper(Looper::prepare(/* opts= */ 0));
280 if (set_sched_policy(0, SP_BACKGROUND) != 0) {
281 ALOGW("Failed to set background scheduling priority to %s thread", kServiceName);
282 }
283 if (int result = pthread_setname_np(pthread_self(), kServiceName); result != 0) {
284 ALOGE("Failed to set %s thread name: %d", kServiceName, result);
285 }
286 mShouldTerminateLooper.store(false);
287 promise.set_value();
288
289 // Loop while PackageInfoResolver is active.
290 // This looper is used to handle package name resolution in asyncFetchPackageNamesForUids.
291 while (!mShouldTerminateLooper) {
292 mHandlerLooper->pollAll(/* timeoutMillis= */ -1);
293 }
294 });
295
296 // Wait until the looper is initialized to ensure no messages get posted
297 // before the looper initialization. Otherwise, messages may be sent to the
298 // looper before it is initialized.
299 if (checkLooperSet.wait_for(std::chrono::seconds(1)) != std::future_status::ready) {
300 ALOGW("Failed to start looper for %s", kServiceName);
301 }
302 }
303
handleMessage(const Message & message)304 void PackageInfoResolver::MessageHandlerImpl::handleMessage(const Message& message) {
305 switch (message.what) {
306 case MSG_RESOLVE_PACKAGE_NAME:
307 kService->resolvePackageName();
308 break;
309 default:
310 ALOGW("Unknown message: %d", message.what);
311 }
312 }
313
314 } // namespace watchdog
315 } // namespace automotive
316 } // namespace android
317