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 #ifndef CPP_WATCHDOG_SERVER_SRC_PACKAGEINFORESOLVER_H_
18 #define CPP_WATCHDOG_SERVER_SRC_PACKAGEINFORESOLVER_H_
19 
20 #include "LooperWrapper.h"
21 #include "WatchdogServiceHelper.h"
22 
23 #include <aidl/android/automotive/watchdog/internal/ApplicationCategoryType.h>
24 #include <aidl/android/automotive/watchdog/internal/PackageInfo.h>
25 #include <android-base/result.h>
26 #include <gtest/gtest_prod.h>
27 #include <utils/Looper.h>
28 #include <utils/Mutex.h>
29 #include <utils/RefBase.h>
30 #include <utils/StrongPointer.h>
31 
32 #include <pwd.h>
33 
34 #include <atomic>
35 #include <functional>
36 #include <queue>
37 #include <shared_mutex>
38 #include <thread>  // NOLINT(build/c++11)
39 #include <unordered_map>
40 #include <unordered_set>
41 
42 namespace android {
43 namespace automotive {
44 namespace watchdog {
45 
46 class ServiceManager;
47 class IoOveruseMonitor;
48 class IoOveruseConfigs;
49 
50 // Forward declaration for testing use only.
51 namespace internal {
52 
53 class PackageInfoResolverPeer;
54 
55 }  // namespace internal
56 
57 class PackageInfoResolverInterface : virtual public android::RefBase {
58 public:
59     virtual void asyncFetchPackageNamesForUids(
60             const std::vector<uid_t>& uids,
61             const std::function<void(std::unordered_map<uid_t, std::string>)>& callback) = 0;
62     virtual std::unordered_map<uid_t, aidl::android::automotive::watchdog::internal::PackageInfo>
63     getPackageInfosForUids(const std::vector<uid_t>& uids) = 0;
64 
65 protected:
66     virtual android::base::Result<void> initWatchdogServiceHelper(
67             const android::sp<WatchdogServiceHelperInterface>& watchdogServiceHelper) = 0;
68     virtual void setPackageConfigurations(
69             const std::unordered_set<std::string>& vendorPackagePrefixes,
70             const std::unordered_map<
71                     std::string,
72                     aidl::android::automotive::watchdog::internal::ApplicationCategoryType>&
73                     packagesToAppCategories) = 0;
74 
75 private:
76     friend class ServiceManager;
77     friend class IoOveruseMonitor;
78     friend class IoOveruseConfigs;
79 };
80 
81 /*
82  * PackageInfoResolver maintains a cache of the UID to PackageInfo mapping in the car watchdog
83  * daemon. PackageInfoResolver is a singleton and must be accessed only via the public static
84  * methods.
85  *
86  * TODO(b/158131194): Extend IUidObserver in WatchdogBinderMediator and use the onUidGone API to
87  *  keep the local mapping cache up-to-date.
88  */
89 class PackageInfoResolver final : public PackageInfoResolverInterface {
90 public:
~PackageInfoResolver()91     ~PackageInfoResolver() {
92         std::unique_lock writeLock(mRWMutex);
93         mWatchdogServiceHelper.clear();
94         mUidToPackageInfoMapping.clear();
95     }
96 
97     /*
98      * Initializes the PackageInfoResolver's singleton instance only on the first call. Main thread
99      * should make the first call as this method doesn't offer multi-threading protection.
100      */
101     static android::sp<PackageInfoResolverInterface> getInstance();
102 
103     android::base::Result<void> initWatchdogServiceHelper(
104             const android::sp<WatchdogServiceHelperInterface>& watchdogServiceHelper);
105 
106     static void terminate();
107 
108     /*
109      * Resolves the given |uids| and returns a mapping of uids to package names via callback. If the
110      * mapping doesn't exist in the local cache, queries the car watchdog service for application
111      * uids and getpwuid for native uids. Logs any error observed during this process.
112      */
113     void asyncFetchPackageNamesForUids(
114             const std::vector<uid_t>& uids,
115             const std::function<void(std::unordered_map<uid_t, std::string>)>& callback);
116 
117     /*
118      * Similar to asyncFetchPackageNamesForUids, resolves the given |uids| and returns a mapping of
119      * uids to package infos.
120      */
121     std::unordered_map<uid_t, aidl::android::automotive::watchdog::internal::PackageInfo>
122     getPackageInfosForUids(const std::vector<uid_t>& uids);
123 
124     virtual void setPackageConfigurations(
125             const std::unordered_set<std::string>& vendorPackagePrefixes,
126             const std::unordered_map<
127                     std::string,
128                     aidl::android::automotive::watchdog::internal::ApplicationCategoryType>&
129                     packagesToAppCategories);
130 
131     class MessageHandlerImpl final : public MessageHandler {
132     public:
MessageHandlerImpl(PackageInfoResolver * service)133         explicit MessageHandlerImpl(PackageInfoResolver* service) : kService(service) {}
134 
135         void handleMessage(const Message& message) override;
136 
137     private:
138         PackageInfoResolver* kService;
139     };
140 
141 private:
142     // PackageInfoResolver instance can only be obtained via |getInstance|.
PackageInfoResolver()143     PackageInfoResolver() :
144           mWatchdogServiceHelper(nullptr),
145           mUidToPackageInfoMapping({}),
146           mVendorPackagePrefixes({}),
147           mShouldTerminateLooper(false),
148           mHandlerLooper(android::sp<LooperWrapper>::make()),
149           mMessageHandler(android::sp<MessageHandlerImpl>::make(this)) {
150         startLooper();
151     }
152 
153     void updatePackageInfos(const std::vector<uid_t>& uids);
154 
155     void resolvePackageName();
156 
157     void startLooper();
158 
159     // Singleton instance.
160     static android::sp<PackageInfoResolver> sInstance;
161 
162     mutable std::shared_mutex mRWMutex;
163 
164     /*
165      * ServiceManager::startServices initializes PackageInfoResolver. However, between the
166      * |getInstance| and |initWatchdogServiceHelper| calls it initializes few other services, which
167      * may call |asyncFetchPackageNamesForUids| or |getPackageInfosForUids| simultaneously on a
168      * separate thread. In order to avoid a race condition between |initWatchdogServiceHelper| and
169      * |getPackage*ForUids| calls, mWatchdogServiceHelper is guarded by a read-write lock.
170      */
171     android::sp<WatchdogServiceHelperInterface> mWatchdogServiceHelper GUARDED_BY(mRWMutex);
172     std::unordered_map<uid_t, aidl::android::automotive::watchdog::internal::PackageInfo>
173             mUidToPackageInfoMapping GUARDED_BY(mRWMutex);
174     std::vector<std::string> mVendorPackagePrefixes GUARDED_BY(mRWMutex);
175     std::unordered_map<std::string,
176                        aidl::android::automotive::watchdog::internal::ApplicationCategoryType>
177             mPackagesToAppCategories GUARDED_BY(mRWMutex);
178     std::atomic<bool> mShouldTerminateLooper;
179     std::thread mHandlerThread;
180     android::sp<LooperWrapper> mHandlerLooper;
181     android::sp<MessageHandlerImpl> mMessageHandler;
182     std::vector<std::pair<std::vector<uid_t>,
183                           std::function<void(std::unordered_map<uid_t, std::string>)>>>
184             mPendingPackageNames GUARDED_BY(mRWMutex);
185 
186     // Required to instantiate the class in |getInstance|.
187     friend class android::sp<PackageInfoResolver>;
188 
189     // For unit tests.
190     static std::function<struct passwd*(uid_t)> sGetpwuidHandler;
191 
192     friend class internal::PackageInfoResolverPeer;
193     FRIEND_TEST(PackageInfoResolverTest, TestResolvesNativeUid);
194     FRIEND_TEST(PackageInfoResolverTest, TestResolvesApplicationUidFromWatchdogServiceHelper);
195     FRIEND_TEST(PackageInfoResolverTest, TestResolvesApplicationUidFromLocalCache);
196 };
197 
198 }  // namespace watchdog
199 }  // namespace automotive
200 }  // namespace android
201 
202 #endif  //  CPP_WATCHDOG_SERVER_SRC_PACKAGEINFORESOLVER_H_
203