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 IPackageInfoResolver : 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<IWatchdogServiceHelper>& 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 : public IPackageInfoResolver { 84 public: 85 /* 86 * Initializes the PackageInfoResolver's singleton instance only on the first call. Main thread 87 * should make the first call as this method doesn't offer multi-threading protection. 88 */ 89 static sp<IPackageInfoResolver> getInstance(); 90 91 /* 92 * Resolves the given |uids| and returns a mapping of uids to package names. If the mapping 93 * doesn't exist in the local cache, queries the car watchdog service for application uids and 94 * getpwuid for native uids. Logs any error observed during this process. 95 */ 96 std::unordered_map<uid_t, std::string> getPackageNamesForUids(const std::vector<uid_t>& uids); 97 98 /* 99 * Similar to getPackageNamesForUids, resolves the given |uids| and returns a mapping of uids to 100 * package infos. 101 */ 102 std::unordered_map<uid_t, android::automotive::watchdog::internal::PackageInfo> 103 getPackageInfosForUids(const std::vector<uid_t>& uids); 104 ~PackageInfoResolver()105 ~PackageInfoResolver() { 106 std::unique_lock writeLock(mRWMutex); 107 mWatchdogServiceHelper.clear(); 108 mUidToPackageInfoMapping.clear(); 109 } 110 111 protected: 112 static void terminate(); 113 114 android::base::Result<void> initWatchdogServiceHelper( 115 const android::sp<IWatchdogServiceHelper>& watchdogServiceHelper); 116 117 virtual void setPackageConfigurations( 118 const std::unordered_set<std::string>& vendorPackagePrefixes, 119 const std::unordered_map< 120 std::string, android::automotive::watchdog::internal::ApplicationCategoryType>& 121 packagesToAppCategories); 122 123 private: 124 // PackageInfoResolver instance can only be obtained via |getInstance|. PackageInfoResolver()125 PackageInfoResolver() : 126 mWatchdogServiceHelper(nullptr), 127 mUidToPackageInfoMapping({}), 128 mVendorPackagePrefixes({}) {} 129 130 void updatePackageInfos(const std::vector<uid_t>& uids); 131 132 // Singleton instance. 133 static android::sp<PackageInfoResolver> sInstance; 134 135 mutable std::shared_mutex mRWMutex; 136 137 /* 138 * ServiceManager::startServices initializes PackageInfoResolver. However, between the 139 * |getInstance| and |initWatchdogServiceHelper| calls it initializes few other services, which 140 * may call |getPackageNamesForUids| or |getPackageInfosForUids| simultaneously on a separate 141 * thread. In order to avoid a race condition between |initWatchdogServiceHelper| and 142 * |getPackage*ForUids| calls, mWatchdogServiceHelper is guarded by a read-write lock. 143 */ 144 android::sp<IWatchdogServiceHelper> mWatchdogServiceHelper GUARDED_BY(mRWMutex); 145 std::unordered_map<uid_t, android::automotive::watchdog::internal::PackageInfo> 146 mUidToPackageInfoMapping GUARDED_BY(mRWMutex); 147 std::vector<std::string> mVendorPackagePrefixes GUARDED_BY(mRWMutex); 148 std::unordered_map<std::string, 149 android::automotive::watchdog::internal::ApplicationCategoryType> 150 mPackagesToAppCategories GUARDED_BY(mRWMutex); 151 152 friend class ServiceManager; 153 friend class IoOveruseMonitor; 154 friend class IoOveruseConfigs; 155 156 // For unit tests. 157 static std::function<struct passwd*(uid_t)> sGetpwuidHandler; 158 159 friend class internal::PackageInfoResolverPeer; 160 FRIEND_TEST(PackageInfoResolverTest, TestResolvesNativeUid); 161 FRIEND_TEST(PackageInfoResolverTest, TestResolvesApplicationUidFromWatchdogServiceHelper); 162 FRIEND_TEST(PackageInfoResolverTest, TestResolvesApplicationUidFromLocalCache); 163 }; 164 165 } // namespace watchdog 166 } // namespace automotive 167 } // namespace android 168 169 #endif // CPP_WATCHDOG_SERVER_SRC_PACKAGEINFORESOLVER_H_ 170