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