• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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