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