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