diff options
author | Lakshman Annadorai <lakshmana@google.com> | 2021-07-09 14:39:23 -0700 |
---|---|---|
committer | Lakshman Annadorai <lakshmana@google.com> | 2021-07-14 15:44:29 -0700 |
commit | c31fc6b04878dbd9e26359a6fc5285a11f914d7c (patch) | |
tree | ea6300703a28c3c4d35142a12f98bfcfeff855d6 /cpp/watchdog | |
parent | 8305437442df424ecea8830e5cb1afc776826025 (diff) | |
download | Car-c31fc6b04878dbd9e26359a6fc5285a11f914d7c.tar.gz |
Handle shared UID in watchdog daemon.
- Daemon should mark a shared UID as safe-to-kill when at least one
package is marked as safe-to-kill in the config.
- Shared package names contain the "shared:" prefix and the package
specific thresholds and safe-to-kill checking are done with the prefix.
- When app cateogry is not mapped by the shared package name, fallback to
fetching app category mapped to any package under the shared UID.
Test: atest libwatchdog_test
Bug: 191892687
Change-Id: If3a0f3887eeac9475b984441b1e1965d72f7720c
Diffstat (limited to 'cpp/watchdog')
-rw-r--r-- | cpp/watchdog/server/src/IoOveruseConfigs.cpp | 33 | ||||
-rw-r--r-- | cpp/watchdog/server/src/PackageInfoResolver.cpp | 20 | ||||
-rw-r--r-- | cpp/watchdog/server/tests/IoOveruseConfigsTest.cpp | 138 | ||||
-rw-r--r-- | cpp/watchdog/server/tests/PackageInfoResolverTest.cpp | 25 |
4 files changed, 204 insertions, 12 deletions
diff --git a/cpp/watchdog/server/src/IoOveruseConfigs.cpp b/cpp/watchdog/server/src/IoOveruseConfigs.cpp index 6fb663397d..96dd6b3c6c 100644 --- a/cpp/watchdog/server/src/IoOveruseConfigs.cpp +++ b/cpp/watchdog/server/src/IoOveruseConfigs.cpp @@ -238,6 +238,16 @@ Result<void> isValidResourceOveruseConfigs( return {}; } +bool isSafeToKillAnyPackage(const std::vector<std::string>& packages, + const std::unordered_set<std::string>& safeToKillPackages) { + for (const auto& packageName : packages) { + if (safeToKillPackages.find(packageName) != safeToKillPackages.end()) { + return true; + } + } + return false; +} + } // namespace IoOveruseConfigs::ParseXmlFileFunction IoOveruseConfigs::sParseXmlFile = @@ -724,11 +734,26 @@ bool IoOveruseConfigs::isSafeToKill(const PackageInfo& packageInfo) const { } switch (packageInfo.componentType) { case ComponentType::SYSTEM: - return mSystemConfig.mSafeToKillPackages.find(packageInfo.packageIdentifier.name) != - mSystemConfig.mSafeToKillPackages.end(); + if (mSystemConfig.mSafeToKillPackages.find(packageInfo.packageIdentifier.name) != + mSystemConfig.mSafeToKillPackages.end()) { + return true; + } + return isSafeToKillAnyPackage(packageInfo.sharedUidPackages, + mSystemConfig.mSafeToKillPackages); case ComponentType::VENDOR: - return mVendorConfig.mSafeToKillPackages.find(packageInfo.packageIdentifier.name) != - mVendorConfig.mSafeToKillPackages.end(); + if (mVendorConfig.mSafeToKillPackages.find(packageInfo.packageIdentifier.name) != + mVendorConfig.mSafeToKillPackages.end()) { + return true; + } + /* + * Packages under the vendor shared UID may contain system packages because when + * CarWatchdogService derives the shared component type it attributes system packages + * as vendor packages when there is at least one vendor package. + */ + return isSafeToKillAnyPackage(packageInfo.sharedUidPackages, + mSystemConfig.mSafeToKillPackages) || + isSafeToKillAnyPackage(packageInfo.sharedUidPackages, + mVendorConfig.mSafeToKillPackages); default: return true; } diff --git a/cpp/watchdog/server/src/PackageInfoResolver.cpp b/cpp/watchdog/server/src/PackageInfoResolver.cpp index 2b30600e7a..84d7c670e7 100644 --- a/cpp/watchdog/server/src/PackageInfoResolver.cpp +++ b/cpp/watchdog/server/src/PackageInfoResolver.cpp @@ -179,9 +179,23 @@ void PackageInfoResolver::updatePackageInfos(const std::vector<uid_t>& uids) { if (id.name.empty()) { continue; } - if (const auto it = mPackagesToAppCategories.find(id.name); - packageInfo.uidType == UidType::APPLICATION && it != mPackagesToAppCategories.end()) { - packageInfo.appCategoryType = it->second; + if (packageInfo.uidType == UidType::APPLICATION) { + if (const auto it = mPackagesToAppCategories.find(id.name); + it != mPackagesToAppCategories.end()) { + packageInfo.appCategoryType = it->second; + } else if (!packageInfo.sharedUidPackages.empty()) { + /* The recommendation for the OEMs is to define the application category mapping + * by the shared package names. However, this a fallback to catch if any mapping is + * defined by the individual package name. + */ + for (const auto& packageName : packageInfo.sharedUidPackages) { + if (const auto it = mPackagesToAppCategories.find(packageName); + it != mPackagesToAppCategories.end()) { + packageInfo.appCategoryType = it->second; + break; + } + } + } } mUidToPackageInfoMapping[id.uid] = packageInfo; } diff --git a/cpp/watchdog/server/tests/IoOveruseConfigsTest.cpp b/cpp/watchdog/server/tests/IoOveruseConfigsTest.cpp index 79b32fcc46..c03ad85eab 100644 --- a/cpp/watchdog/server/tests/IoOveruseConfigsTest.cpp +++ b/cpp/watchdog/server/tests/IoOveruseConfigsTest.cpp @@ -75,12 +75,14 @@ std::unordered_map<std::string, ApplicationCategoryType> toPackageToAppCategoryM PackageInfo constructPackageInfo( const char* packageName, const ComponentType componentType, - const ApplicationCategoryType appCategoryType = ApplicationCategoryType::OTHERS) { + const ApplicationCategoryType appCategoryType = ApplicationCategoryType::OTHERS, + const std::vector<std::string>& sharedUidPackages = std::vector<std::string>()) { PackageInfo packageInfo; packageInfo.packageIdentifier.name = packageName; packageInfo.uidType = UidType::APPLICATION; packageInfo.componentType = componentType; packageInfo.appCategoryType = appCategoryType; + packageInfo.sharedUidPackages = sharedUidPackages; return packageInfo; } @@ -832,6 +834,28 @@ TEST_F(IoOveruseConfigsTest, TestFetchThresholdForSystemPackages) { EXPECT_THAT(actual, MEDIA_THRESHOLDS); } +TEST_F(IoOveruseConfigsTest, TestFetchThresholdForSharedSystemPackages) { + const auto ioOveruseConfigs = sampleIoOveruseConfigs(); + auto sampleSystemConfig = sampleUpdateSystemConfig(); + auto& ioConfig = sampleSystemConfig.resourceSpecificConfigurations[0] + .get<ResourceSpecificConfiguration::ioOveruseConfiguration>(); + ioConfig.packageSpecificThresholds.push_back( + toPerStateIoOveruseThreshold("shared:systemSharedPackage", + toPerStateBytes(100, 200, 300))); + + ioOveruseConfigs->update({sampleSystemConfig}); + + auto actual = ioOveruseConfigs->fetchThreshold( + constructPackageInfo("shared:systemSharedPackage", ComponentType::SYSTEM)); + + EXPECT_THAT(actual, toPerStateBytes(100, 200, 300)); + + actual = ioOveruseConfigs->fetchThreshold( + constructPackageInfo("systemSharedPackage", ComponentType::SYSTEM)); + + EXPECT_THAT(actual, SYSTEM_COMPONENT_LEVEL_THRESHOLDS); +} + TEST_F(IoOveruseConfigsTest, TestFetchThresholdForVendorPackages) { const auto ioOveruseConfigs = sampleIoOveruseConfigs(); @@ -853,6 +877,28 @@ TEST_F(IoOveruseConfigsTest, TestFetchThresholdForVendorPackages) { EXPECT_THAT(actual, MAPS_THRESHOLDS); } +TEST_F(IoOveruseConfigsTest, TestFetchThresholdForSharedVendorPackages) { + const auto ioOveruseConfigs = sampleIoOveruseConfigs(); + auto sampleVendorConfig = sampleUpdateVendorConfig(); + auto& ioConfig = sampleVendorConfig.resourceSpecificConfigurations[0] + .get<ResourceSpecificConfiguration::ioOveruseConfiguration>(); + ioConfig.packageSpecificThresholds.push_back( + toPerStateIoOveruseThreshold("shared:vendorSharedPackage", + toPerStateBytes(100, 200, 300))); + + ioOveruseConfigs->update({sampleVendorConfig}); + + auto actual = ioOveruseConfigs->fetchThreshold( + constructPackageInfo("shared:vendorSharedPackage", ComponentType::VENDOR)); + + EXPECT_THAT(actual, toPerStateBytes(100, 200, 300)); + + actual = ioOveruseConfigs->fetchThreshold( + constructPackageInfo("vendorSharedPackage", ComponentType::VENDOR)); + + EXPECT_THAT(actual, VENDOR_COMPONENT_LEVEL_THRESHOLDS); +} + TEST_F(IoOveruseConfigsTest, TestFetchThresholdForThirdPartyPackages) { const auto ioOveruseConfigs = sampleIoOveruseConfigs(); @@ -883,6 +929,36 @@ TEST_F(IoOveruseConfigsTest, TestIsSafeToKillSystemPackages) { constructPackageInfo("systemPackageA", ComponentType::SYSTEM))); } +TEST_F(IoOveruseConfigsTest, TestIsSafeToKillSharedSystemPackages) { + auto sampleSystemConfig = sampleUpdateSystemConfig(); + sampleSystemConfig.safeToKillPackages.push_back("sharedUidSystemPackageC"); + sampleSystemConfig.safeToKillPackages.push_back("shared:systemSharedPackageD"); + sp<IoOveruseConfigs> ioOveruseConfigs = new IoOveruseConfigs(); + + EXPECT_RESULT_OK(ioOveruseConfigs->update({sampleSystemConfig})); + + PackageInfo packageInfo = + constructPackageInfo("systemSharedPackage", ComponentType::SYSTEM, + ApplicationCategoryType::OTHERS, + {"sharedUidSystemPackageA", "sharedUidSystemPackageB", + "sharedUidSystemPackageC"}); + + EXPECT_TRUE(ioOveruseConfigs->isSafeToKill(packageInfo)) + << "Should be safe-to-kill when at least one package under shared UID is safe-to-kill"; + + packageInfo = + constructPackageInfo("shared:systemSharedPackageD", ComponentType::SYSTEM, + ApplicationCategoryType::OTHERS, {"sharedUidSystemPackageA"}); + EXPECT_TRUE(ioOveruseConfigs->isSafeToKill(packageInfo)) + << "Should be safe-to-kill when shared package is safe-to-kill"; + + packageInfo = + constructPackageInfo("systemSharedPackageD", ComponentType::SYSTEM, + ApplicationCategoryType::OTHERS, {"sharedUidSystemPackageA"}); + EXPECT_FALSE(ioOveruseConfigs->isSafeToKill(packageInfo)) + << "Shouldn't be safe-to-kill when the 'shared:' prefix is missing"; +} + TEST_F(IoOveruseConfigsTest, TestIsSafeToKillVendorPackages) { const auto ioOveruseConfigs = sampleIoOveruseConfigs(); EXPECT_FALSE(ioOveruseConfigs->isSafeToKill( @@ -892,6 +968,40 @@ TEST_F(IoOveruseConfigsTest, TestIsSafeToKillVendorPackages) { constructPackageInfo("vendorPackageA", ComponentType::VENDOR))); } +TEST_F(IoOveruseConfigsTest, TestIsSafeToKillSharedVendorPackages) { + auto sampleVendorConfig = sampleUpdateVendorConfig(); + sampleVendorConfig.safeToKillPackages.push_back("sharedUidVendorPackageC"); + sampleVendorConfig.safeToKillPackages.push_back("shared:vendorSharedPackageD"); + + auto sampleSystemConfig = sampleUpdateSystemConfig(); + sampleSystemConfig.safeToKillPackages.push_back("sharedUidSystemPackageC"); + + sp<IoOveruseConfigs> ioOveruseConfigs = new IoOveruseConfigs(); + + EXPECT_RESULT_OK(ioOveruseConfigs->update({sampleSystemConfig, sampleVendorConfig})); + + PackageInfo packageInfo = + constructPackageInfo("vendorSharedPackage", ComponentType::VENDOR, + ApplicationCategoryType::OTHERS, + {"sharedUidVendorPackageA", "sharedUidVendorPackageB", + "sharedUidVendorPackageC"}); + + EXPECT_TRUE(ioOveruseConfigs->isSafeToKill(packageInfo)) + << "Should be safe-to-kill when at least one package under shared UID is safe-to-kill"; + + packageInfo = + constructPackageInfo("shared:vendorSharedPackageD", ComponentType::VENDOR, + ApplicationCategoryType::OTHERS, {"sharedUidVendorPackageA"}); + EXPECT_TRUE(ioOveruseConfigs->isSafeToKill(packageInfo)) + << "Should be safe-to-kill when shared package is safe-to-kill"; + + packageInfo = + constructPackageInfo("shared:vendorSharedPackageE", ComponentType::VENDOR, + ApplicationCategoryType::OTHERS, {"sharedUidVendorPackageA"}); + EXPECT_FALSE(ioOveruseConfigs->isSafeToKill(packageInfo)) + << "Shouldn't be safe-to-kill when the 'shared:' prefix is missing"; +} + TEST_F(IoOveruseConfigsTest, TestIsSafeToKillThirdPartyPackages) { const auto ioOveruseConfigs = sampleIoOveruseConfigs(); EXPECT_TRUE(ioOveruseConfigs->isSafeToKill( @@ -931,6 +1041,32 @@ TEST_F(IoOveruseConfigsTest, TestVendorPackagePrefixes) { UnorderedElementsAre("vendorPackage", "vendorPkgB")); } +TEST_F(IoOveruseConfigsTest, TestVendorPackagePrefixesWithSharedPackages) { + auto sampleVendorConfig = sampleUpdateVendorConfig(); + sampleVendorConfig.vendorPackagePrefixes.push_back("shared:vendorSharedPackage"); + sampleVendorConfig.safeToKillPackages.push_back("sharedUidVendorPackageD"); + sampleVendorConfig.safeToKillPackages.push_back("shared:vendorSharedPackageE"); + sampleVendorConfig.safeToKillPackages.push_back("shared:vndrSharedPkgF"); + + auto& ioConfig = sampleVendorConfig.resourceSpecificConfigurations[0] + .get<ResourceSpecificConfiguration::ioOveruseConfiguration>(); + + ioConfig.packageSpecificThresholds.push_back( + toPerStateIoOveruseThreshold("shared:vendorSharedPackageG", + VENDOR_PACKAGE_A_THRESHOLDS)); + ioConfig.packageSpecificThresholds.push_back( + toPerStateIoOveruseThreshold("shared:vndrSharedPkgH", VENDOR_PACKAGE_A_THRESHOLDS)); + + sp<IoOveruseConfigs> ioOveruseConfigs = new IoOveruseConfigs(); + + EXPECT_RESULT_OK(ioOveruseConfigs->update({sampleVendorConfig})); + + EXPECT_THAT(ioOveruseConfigs->vendorPackagePrefixes(), + UnorderedElementsAre("vendorPackage", "vendorPkgB", "shared:vendorSharedPackage", + "sharedUidVendorPackageD", "shared:vndrSharedPkgF", + "shared:vndrSharedPkgH")); +} + TEST_F(IoOveruseConfigsTest, TestPackagesToAppCategoriesWithSystemConfig) { IoOveruseConfigs ioOveruseConfigs; const auto resourceOveruseConfig = sampleUpdateSystemConfig(); diff --git a/cpp/watchdog/server/tests/PackageInfoResolverTest.cpp b/cpp/watchdog/server/tests/PackageInfoResolverTest.cpp index f2fe3a69a1..cf282be5fb 100644 --- a/cpp/watchdog/server/tests/PackageInfoResolverTest.cpp +++ b/cpp/watchdog/server/tests/PackageInfoResolverTest.cpp @@ -195,6 +195,8 @@ TEST(PackageInfoResolverTest, TestGetPackageInfosForUidsViaWatchdogService) { // system.package.B is native package so this should be ignored. {"system.package.B", ApplicationCategoryType::MAPS}, {"vendor.package.A", ApplicationCategoryType::MEDIA}, + {"shared:vendor.package.C", ApplicationCategoryType::MEDIA}, + {"vendor.package.shared.uid.D", ApplicationCategoryType::MAPS}, }; peer.setPackageConfigurations({"vendor.pkg"}, packagesToAppCategories); /* @@ -213,23 +215,38 @@ TEST(PackageInfoResolverTest, TestGetPackageInfosForUidsViaWatchdogService) { ApplicationCategoryType::OTHERS)}, {15100, constructPackageInfo("vendor.package.A", 15100, UidType::APPLICATION, - ComponentType::VENDOR, ApplicationCategoryType::MEDIA)}, + ComponentType::VENDOR, ApplicationCategoryType::OTHERS)}, {16700, constructPackageInfo("vendor.pkg", 16700, UidType::NATIVE, ComponentType::VENDOR, ApplicationCategoryType::OTHERS)}, + {18100, + constructPackageInfo("shared:vendor.package.C", 18100, UidType::APPLICATION, + ComponentType::VENDOR, ApplicationCategoryType::OTHERS)}, + {19100, + constructPackageInfo("shared:vendor.package.D", 19100, UidType::APPLICATION, + ComponentType::VENDOR, ApplicationCategoryType::OTHERS, + {"vendor.package.shared.uid.D"})}, }; - std::vector<int32_t> expectedUids = {6100, 7700, 15100, 16700}; + std::vector<int32_t> expectedUids = {6100, 7700, 15100, 16700, 18100, 19100}; std::vector<std::string> expectedPrefixes = {"vendor.pkg"}; std::vector<PackageInfo> injectPackageInfos = {expectedMappings.at(6100), expectedMappings.at(7700), expectedMappings.at(15100), - expectedMappings.at(16700)}; + expectedMappings.at(16700), + expectedMappings.at(18100), + expectedMappings.at(19100)}; + + expectedMappings.at(15100).appCategoryType = ApplicationCategoryType::MEDIA; + expectedMappings.at(18100).appCategoryType = ApplicationCategoryType::MEDIA; + expectedMappings.at(19100).appCategoryType = ApplicationCategoryType::MAPS; + EXPECT_CALL(*peer.mockWatchdogServiceHelper, getPackageInfosForUids(expectedUids, expectedPrefixes, _)) .WillOnce(DoAll(SetArgPointee<2>(injectPackageInfos), Return(binder::Status::ok()))); - auto actualMappings = packageInfoResolver->getPackageInfosForUids({6100, 7700, 15100, 16700}); + auto actualMappings = + packageInfoResolver->getPackageInfosForUids({6100, 7700, 15100, 16700, 18100, 19100}); EXPECT_THAT(actualMappings, UnorderedElementsAreArray(expectedMappings)) << "Expected: " << toString(expectedMappings) |