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