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