aboutsummaryrefslogtreecommitdiff
path: root/cpp/watchdog
diff options
context:
space:
mode:
authorLakshman Annadorai <lakshmana@google.com>2021-05-19 09:00:42 -0700
committerLakshman Annadorai <lakshmana@google.com>2021-05-25 11:03:24 -0700
commit9fb0eea0dc710d8568975e840e42463bbb733e85 (patch)
treeb6a0bab827f89fd97eaee4e4005187334df89b83 /cpp/watchdog
parent80998b44e30141ea450c45988999d5df13c800b7 (diff)
downloadCar-9fb0eea0dc710d8568975e840e42463bbb733e85.tar.gz
Implement resource overuse config XML parser.
The XML parser will be used by the I/O overuse monitoring module to parse on device XML config. Test: atest libwatchdog_test Bug: 186445673 Change-Id: I4415c315116ea75e8da1c4c535440e8e5bf6f750
Diffstat (limited to 'cpp/watchdog')
-rw-r--r--cpp/watchdog/server/Android.bp12
-rw-r--r--cpp/watchdog/server/src/OveruseConfigurationXmlHelper.cpp474
-rw-r--r--cpp/watchdog/server/src/OveruseConfigurationXmlHelper.h44
-rw-r--r--cpp/watchdog/server/tests/IoOveruseConfigsTest.cpp151
-rw-r--r--cpp/watchdog/server/tests/OveruseConfigurationTestUtils.cpp170
-rw-r--r--cpp/watchdog/server/tests/OveruseConfigurationTestUtils.h88
-rw-r--r--cpp/watchdog/server/tests/OveruseConfigurationXmlHelperTest.cpp159
-rw-r--r--cpp/watchdog/server/tests/data/duplicate_component_io_thresholds_overuse_configuration.xml31
-rw-r--r--cpp/watchdog/server/tests/data/duplicate_component_type_overuse_configuration.xml27
-rw-r--r--cpp/watchdog/server/tests/data/duplicate_io_config_overuse_configuration.xml33
-rw-r--r--cpp/watchdog/server/tests/data/incomplete_app_category_io_thresholds_overuse_configuration.xml34
-rw-r--r--cpp/watchdog/server/tests/data/incomplete_component_io_thresholds_overuse_configuration.xml25
-rw-r--r--cpp/watchdog/server/tests/data/incomplete_pkg_io_thresholds_overuse_configuration.xml32
-rw-r--r--cpp/watchdog/server/tests/data/incomplete_systemwide_io_thresholds_overuse_configuration.xml31
-rw-r--r--cpp/watchdog/server/tests/data/invalid_component_type_overuse_configuration.xml26
-rw-r--r--cpp/watchdog/server/tests/data/invalid_param_systemwide_io_thresholds_overuse_configuration.xml33
-rw-r--r--cpp/watchdog/server/tests/data/invalid_state_app_category_io_thresholds_overuse_configuration.xml36
-rw-r--r--cpp/watchdog/server/tests/data/invalid_state_component_io_thresholds_overuse_configuration.xml27
-rw-r--r--cpp/watchdog/server/tests/data/invalid_state_pkg_io_thresholds_overuse_configuration.xml34
-rw-r--r--cpp/watchdog/server/tests/data/invalid_type_app_category_mapping_overuse_configuration.xml32
-rw-r--r--cpp/watchdog/server/tests/data/missing_component_io_thresholds_overuse_configuration.xml20
-rw-r--r--cpp/watchdog/server/tests/data/missing_io_config_overuse_configuration.xml19
-rw-r--r--cpp/watchdog/server/tests/data/missing_pkg_name_app_category_mapping_overuse_configuration.xml32
-rw-r--r--cpp/watchdog/server/tests/data/missing_pkg_name_pkg_io_thresholds_overuse_configuration.xml33
-rw-r--r--cpp/watchdog/server/tests/data/missing_pkg_name_safe_to_kill_entry_overuse_configuration.xml31
-rw-r--r--cpp/watchdog/server/tests/data/missing_threshold_app_category_io_thresholds_overuse_configuration.xml35
-rw-r--r--cpp/watchdog/server/tests/data/missing_threshold_component_io_thresholds_overuse_configuration.xml26
-rw-r--r--cpp/watchdog/server/tests/data/missing_threshold_pkg_io_thresholds_overuse_configuration.xml33
-rw-r--r--cpp/watchdog/server/tests/data/missing_threshold_systemwide_io_thresholds_overuse_configuration.xml32
-rw-r--r--cpp/watchdog/server/tests/data/valid_overuse_system_configuration.xml64
-rw-r--r--cpp/watchdog/server/tests/data/valid_overuse_third_party_configuration.xml27
-rw-r--r--cpp/watchdog/server/tests/data/valid_overuse_vendor_configuration.xml75
32 files changed, 1783 insertions, 143 deletions
diff --git a/cpp/watchdog/server/Android.bp b/cpp/watchdog/server/Android.bp
index a0d85b845d..9b5b973173 100644
--- a/cpp/watchdog/server/Android.bp
+++ b/cpp/watchdog/server/Android.bp
@@ -66,6 +66,7 @@ cc_defaults {
shared_libs: [
"libcutils",
"libprocessgroup",
+ "libtinyxml2",
"libwatchdog_package_info_resolver",
],
}
@@ -82,6 +83,7 @@ cc_library {
"src/IoOveruseMonitor.cpp",
"src/IoPerfCollection.cpp",
"src/LooperWrapper.cpp",
+ "src/OveruseConfigurationXmlHelper.cpp",
"src/ProcDiskStats.cpp",
"src/ProcPidStat.cpp",
"src/ProcStat.cpp",
@@ -95,6 +97,13 @@ cc_library {
],
}
+filegroup {
+ name: "watchdog_test_xml_files",
+ srcs: [
+ "tests/data/*.xml",
+ ],
+}
+
cc_test {
name: "libwatchdog_test",
defaults: [
@@ -108,6 +117,8 @@ cc_test {
"tests/IoOveruseMonitorTest.cpp",
"tests/IoPerfCollectionTest.cpp",
"tests/LooperStub.cpp",
+ "tests/OveruseConfigurationTestUtils.cpp",
+ "tests/OveruseConfigurationXmlHelperTest.cpp",
"tests/PackageInfoResolverTest.cpp",
"tests/ProcDiskStatsTest.cpp",
"tests/ProcPidDir.cpp",
@@ -128,6 +139,7 @@ cc_test {
"libwatchdog_process_service",
"libwatchdog_package_info_resolver",
],
+ data: [":watchdog_test_xml_files"],
}
cc_defaults {
diff --git a/cpp/watchdog/server/src/OveruseConfigurationXmlHelper.cpp b/cpp/watchdog/server/src/OveruseConfigurationXmlHelper.cpp
new file mode 100644
index 0000000000..f76bcc5737
--- /dev/null
+++ b/cpp/watchdog/server/src/OveruseConfigurationXmlHelper.cpp
@@ -0,0 +1,474 @@
+/*
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "carwatchdogd"
+
+#include "OveruseConfigurationXmlHelper.h"
+
+#include <android-base/parseint.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <android/automotive/watchdog/PerStateBytes.h>
+#include <android/automotive/watchdog/internal/ApplicationCategoryType.h>
+#include <android/automotive/watchdog/internal/ComponentType.h>
+#include <android/automotive/watchdog/internal/IoOveruseAlertThreshold.h>
+#include <android/automotive/watchdog/internal/IoOveruseConfiguration.h>
+#include <android/automotive/watchdog/internal/PackageMetadata.h>
+#include <android/automotive/watchdog/internal/PerStateIoOveruseThreshold.h>
+#include <android/automotive/watchdog/internal/ResourceSpecificConfiguration.h>
+
+#include <tinyxml2.h>
+
+#include <unordered_set>
+#include <vector>
+
+namespace android {
+namespace automotive {
+namespace watchdog {
+
+using ::android::automotive::watchdog::PerStateBytes;
+using ::android::automotive::watchdog::internal::ApplicationCategoryType;
+using ::android::automotive::watchdog::internal::ComponentType;
+using ::android::automotive::watchdog::internal::IoOveruseAlertThreshold;
+using ::android::automotive::watchdog::internal::IoOveruseConfiguration;
+using ::android::automotive::watchdog::internal::PackageMetadata;
+using ::android::automotive::watchdog::internal::PerStateIoOveruseThreshold;
+using ::android::automotive::watchdog::internal::ResourceOveruseConfiguration;
+using ::android::automotive::watchdog::internal::ResourceSpecificConfiguration;
+using ::android::base::EqualsIgnoreCase;
+using ::android::base::Error;
+using ::android::base::Join;
+using ::android::base::ParseInt;
+using ::android::base::Result;
+using ::android::base::StartsWith;
+using ::android::base::StringAppendF;
+using ::android::base::StringPrintf;
+using ::android::base::Trim;
+using ::android::binder::Status;
+using ::tinyxml2::XML_SUCCESS;
+using ::tinyxml2::XMLDocument;
+using ::tinyxml2::XMLElement;
+
+namespace {
+constexpr const char kTagResourceOveruseConfiguration[] = "resourceOveruseConfiguration";
+constexpr const char kTagComponentType[] = "componentType";
+
+constexpr const char kTagSafeToKillPackages[] = "safeToKillPackages";
+constexpr const char kTagPackage[] = "package";
+
+constexpr const char kTagVendorPackagePrefixes[] = "vendorPackagePrefixes";
+constexpr const char kTagPackagePrefix[] = "packagePrefix";
+
+constexpr const char kTagPackageToAppCategoryTypes[] = "packagesToAppCategoryTypes";
+constexpr const char kTagPackageAppCategory[] = "packageAppCategory";
+
+constexpr const char kTagIoOveruseConfiguration[] = "ioOveruseConfiguration";
+constexpr const char kTagComponentLevelThresholds[] = "componentLevelThresholds";
+constexpr const char kTagPackageSpecificThresholds[] = "packageSpecificThresholds";
+constexpr const char kTagState[] = "state";
+constexpr const char kStateIdForegroundMode[] = "foreground_mode";
+constexpr const char kStateIdBackgroundMode[] = "background_mode";
+constexpr const char kStateIdGarageMode[] = "garage_mode";
+constexpr int kNumStates = 3;
+
+constexpr const char kTagAppCategorySpecificThresholds[] = "appCategorySpecificThresholds";
+constexpr const char kTagAppCategoryThreshold[] = "appCategoryThreshold";
+
+constexpr const char kTagSystemWideThresholds[] = "systemWideThresholds";
+constexpr const char kTagParam[] = "param";
+constexpr const char kParamIdDurationSeconds[] = "duration_seconds";
+constexpr const char kParamIdWrittenBytesPerSecond[] = "written_bytes_per_second";
+constexpr int kNumParams = 2;
+
+constexpr const char kAttrId[] = "id";
+constexpr const char kAttrType[] = "type";
+
+Result<const XMLElement*> readExactlyOneElement(const char* tag, const XMLElement* rootElement) {
+ const XMLElement* element = rootElement->FirstChildElement(tag);
+ if (element == nullptr) {
+ return Error() << "Must specify value for the tag '" << tag << "'";
+ }
+ if (element->NextSiblingElement(tag) != nullptr) {
+ return Error() << "Must specify only one entry for the tag '" << tag << "'";
+ }
+ return element;
+}
+
+Result<ComponentType> readComponentType(const XMLElement* rootElement) {
+ const XMLElement* componentTypeElement;
+ if (const auto result = readExactlyOneElement(kTagComponentType, rootElement); result.ok()) {
+ componentTypeElement = *result;
+ } else {
+ return Error() << "Failed to read tag '" << kTagComponentType << "': " << result.error();
+ }
+ std::string componentTypeStr;
+ if (const auto text = componentTypeElement->GetText(); text == nullptr) {
+ return Error() << "Must specify non-empty component type";
+ } else if (componentTypeStr = Trim(text); componentTypeStr.empty()) {
+ return Error() << "Must specify non-empty component type";
+ }
+ static const std::string* const kSystemComponent =
+ new std::string(toString(ComponentType::SYSTEM));
+ static const std::string* const kVendorComponent =
+ new std::string(toString(ComponentType::VENDOR));
+ static const std::string* const kThirdPartyComponent =
+ new std::string(toString(ComponentType::THIRD_PARTY));
+ if (EqualsIgnoreCase(componentTypeStr, *kSystemComponent)) {
+ return ComponentType::SYSTEM;
+ } else if (EqualsIgnoreCase(componentTypeStr, *kVendorComponent)) {
+ return ComponentType::VENDOR;
+ } else if (EqualsIgnoreCase(componentTypeStr, *kThirdPartyComponent)) {
+ return ComponentType::THIRD_PARTY;
+ }
+ return Error() << "Must specify valid component type. Received " << componentTypeStr;
+}
+
+Result<std::vector<std::string>> readSafeToKillPackages(const XMLElement* rootElement) {
+ std::vector<std::string> safeToKillPackages;
+ for (const XMLElement* outerElement = rootElement->FirstChildElement(kTagSafeToKillPackages);
+ outerElement != nullptr;
+ outerElement = outerElement->NextSiblingElement(kTagSafeToKillPackages)) {
+ for (const XMLElement* innerElement = outerElement->FirstChildElement(kTagPackage);
+ innerElement != nullptr;
+ innerElement = innerElement->NextSiblingElement(kTagPackage)) {
+ std::string packageName;
+ if (const auto text = innerElement->GetText(); text == nullptr) {
+ return Error() << "Must specify non-empty safe-to-kill package name";
+ } else if (packageName = Trim(text); packageName.empty()) {
+ return Error() << "Must specify non-empty safe-to-kill package name";
+ }
+ safeToKillPackages.push_back(std::string(packageName));
+ }
+ }
+ return safeToKillPackages;
+}
+
+Result<std::vector<std::string>> readVendorPackagePrefixes(const XMLElement* rootElement) {
+ std::vector<std::string> vendorPackagePrefixes;
+ for (const XMLElement* outerElement = rootElement->FirstChildElement(kTagVendorPackagePrefixes);
+ outerElement != nullptr;
+ outerElement = outerElement->NextSiblingElement(kTagVendorPackagePrefixes)) {
+ for (const XMLElement* innerElement = outerElement->FirstChildElement(kTagPackagePrefix);
+ innerElement != nullptr;
+ innerElement = innerElement->NextSiblingElement(kTagPackagePrefix)) {
+ std::string packagePrefix;
+ if (const auto text = innerElement->GetText(); text == nullptr) {
+ return Error() << "Must specify non-empty vendor package prefix";
+ } else if (packagePrefix = Trim(text); packagePrefix.empty()) {
+ return Error() << "Must specify non-empty vendor package prefix";
+ }
+ vendorPackagePrefixes.push_back(std::string(packagePrefix));
+ }
+ }
+ return vendorPackagePrefixes;
+}
+
+ApplicationCategoryType toApplicationCategoryType(std::string_view value) {
+ static const std::string* const kMapsAppCategory =
+ new std::string(toString(ApplicationCategoryType::MAPS));
+ static const std::string* const kMediaAppCategory =
+ new std::string(toString(ApplicationCategoryType::MEDIA));
+ if (EqualsIgnoreCase(value, *kMapsAppCategory)) {
+ return ApplicationCategoryType::MAPS;
+ } else if (EqualsIgnoreCase(value, *kMediaAppCategory)) {
+ return ApplicationCategoryType::MEDIA;
+ }
+ return ApplicationCategoryType::OTHERS;
+}
+
+Result<std::vector<PackageMetadata>> readPackageToAppCategoryTypes(const XMLElement* rootElement) {
+ std::vector<PackageMetadata> packageMetadata;
+ for (const XMLElement* outerElement =
+ rootElement->FirstChildElement(kTagPackageToAppCategoryTypes);
+ outerElement != nullptr;
+ outerElement = outerElement->NextSiblingElement(kTagPackageToAppCategoryTypes)) {
+ for (const XMLElement* innerElement =
+ outerElement->FirstChildElement(kTagPackageAppCategory);
+ innerElement != nullptr;
+ innerElement = innerElement->NextSiblingElement(kTagPackageAppCategory)) {
+ const char* type = nullptr;
+ if (innerElement->QueryStringAttribute(kAttrType, &type) != XML_SUCCESS) {
+ return Error() << "Failed to read '" << kAttrType << "' attribute in '"
+ << kTagPackageAppCategory << "' tag";
+ }
+ PackageMetadata meta;
+ if (meta.appCategoryType = toApplicationCategoryType(type);
+ meta.appCategoryType == ApplicationCategoryType::OTHERS) {
+ return Error() << "Must specify valid app category type. Received " << type;
+ }
+ if (const auto text = innerElement->GetText(); text == nullptr) {
+ return Error() << "Must specify non-empty package name";
+ } else if (meta.packageName = Trim(text); meta.packageName.empty()) {
+ return Error() << "Must specify non-empty package name";
+ }
+ packageMetadata.push_back(meta);
+ }
+ }
+ return packageMetadata;
+}
+
+Result<PerStateBytes> readPerStateBytes(const XMLElement* rootElement) {
+ PerStateBytes perStateBytes;
+ std::unordered_set<std::string> seenStates;
+ for (const XMLElement* childElement = rootElement->FirstChildElement(kTagState);
+ childElement != nullptr; childElement = childElement->NextSiblingElement(kTagState)) {
+ const char* state = nullptr;
+ if (childElement->QueryStringAttribute(kAttrId, &state) != XML_SUCCESS) {
+ return Error() << "Failed to read '" << kAttrId << "' attribute in '" << kTagState
+ << "' tag";
+ }
+ if (seenStates.find(state) != seenStates.end()) {
+ return Error() << "Duplicate threshold specified for state '" << state << "'";
+ }
+ int64_t bytes = 0;
+ if (const auto text = childElement->GetText(); text == nullptr) {
+ return Error() << "Must specify non-empty threshold for state '" << state << "'";
+ } else if (const auto bytesStr = Trim(text); !ParseInt(bytesStr.c_str(), &bytes)) {
+ return Error() << "Failed to parse threshold for the state '" << state
+ << "': Received threshold value '" << bytesStr << "'";
+ }
+ if (!strcmp(state, kStateIdForegroundMode)) {
+ seenStates.insert(kStateIdForegroundMode);
+ perStateBytes.foregroundBytes = bytes;
+ } else if (!strcmp(state, kStateIdBackgroundMode)) {
+ seenStates.insert(kStateIdBackgroundMode);
+ perStateBytes.backgroundBytes = bytes;
+ } else if (!strcmp(state, kStateIdGarageMode)) {
+ seenStates.insert(kStateIdGarageMode);
+ perStateBytes.garageModeBytes = bytes;
+ } else {
+ return Error() << "Invalid state '" << state << "' in per-state bytes";
+ }
+ }
+ if (seenStates.size() != kNumStates) {
+ return Error() << "Thresholds not specified for all states. Specified only for ["
+ << Join(seenStates, ", ") << "] states";
+ }
+ return perStateBytes;
+}
+
+Result<PerStateIoOveruseThreshold> readComponentLevelThresholds(ComponentType componentType,
+ const XMLElement* rootElement) {
+ const XMLElement* componentLevelThresholdElement = nullptr;
+ if (const auto result = readExactlyOneElement(kTagComponentLevelThresholds, rootElement);
+ result.ok()) {
+ componentLevelThresholdElement = *result;
+ } else {
+ return Error() << "Failed to read tag '" << kTagComponentLevelThresholds
+ << "': " << result.error();
+ }
+ PerStateIoOveruseThreshold thresholds;
+ thresholds.name = toString(componentType);
+ if (const auto result = readPerStateBytes(componentLevelThresholdElement); result.ok()) {
+ thresholds.perStateWriteBytes = *result;
+ } else {
+ return Error() << "Failed to read component level thresholds for component '"
+ << thresholds.name << "': " << result.error();
+ }
+ return thresholds;
+}
+
+Result<std::vector<PerStateIoOveruseThreshold>> readPackageSpecificThresholds(
+ const XMLElement* rootElement) {
+ std::vector<PerStateIoOveruseThreshold> thresholds;
+ for (const XMLElement* childElement =
+ rootElement->FirstChildElement(kTagPackageSpecificThresholds);
+ childElement != nullptr;
+ childElement = childElement->NextSiblingElement(kTagPackageSpecificThresholds)) {
+ PerStateIoOveruseThreshold threshold;
+ if (const char* name = nullptr;
+ childElement->QueryStringAttribute(kAttrId, &name) != XML_SUCCESS) {
+ return Error() << "Failed to read '" << kAttrId << "' attribute in '"
+ << kTagPackageSpecificThresholds << "' tag";
+ } else if (threshold.name = name; threshold.name.empty()) {
+ return Error() << "Must provide non-empty package name in '" << kAttrId
+ << "attribute in '" << kTagPackageSpecificThresholds << "' tag";
+ }
+ if (const auto result = readPerStateBytes(childElement); result.ok()) {
+ threshold.perStateWriteBytes = *result;
+ } else {
+ return Error() << "Failed to read package specific thresholds for package '"
+ << threshold.name << "': " << result.error();
+ }
+ thresholds.push_back(threshold);
+ }
+ return thresholds;
+}
+
+Result<std::vector<PerStateIoOveruseThreshold>> readAppCategorySpecificThresholds(
+ const XMLElement* rootElement) {
+ std::vector<PerStateIoOveruseThreshold> thresholds;
+ for (const XMLElement* outerElement =
+ rootElement->FirstChildElement(kTagAppCategorySpecificThresholds);
+ outerElement != nullptr;
+ outerElement = outerElement->NextSiblingElement(kTagAppCategorySpecificThresholds)) {
+ for (const XMLElement* innerElement =
+ outerElement->FirstChildElement(kTagAppCategoryThreshold);
+ innerElement != nullptr;
+ innerElement = innerElement->NextSiblingElement(kTagAppCategoryThreshold)) {
+ const char* name = nullptr;
+ if (innerElement->QueryStringAttribute(kAttrId, &name) != XML_SUCCESS) {
+ return Error() << "Failed to read '" << kAttrId << "' attribute in '"
+ << kTagAppCategoryThreshold << "' tag";
+ }
+ PerStateIoOveruseThreshold threshold;
+ threshold.name = name;
+ if (const auto result = readPerStateBytes(innerElement); result.ok()) {
+ threshold.perStateWriteBytes = *result;
+ } else {
+ return Error() << "Failed to read app category specific thresholds for application "
+ << "category '" << threshold.name << "': " << result.error();
+ }
+ thresholds.push_back(threshold);
+ }
+ }
+ return thresholds;
+}
+
+Result<std::vector<IoOveruseAlertThreshold>> readSystemWideThresholds(
+ const XMLElement* rootElement) {
+ std::vector<IoOveruseAlertThreshold> alertThresholds;
+ for (const XMLElement* outerElement = rootElement->FirstChildElement(kTagSystemWideThresholds);
+ outerElement != nullptr;
+ outerElement = outerElement->NextSiblingElement(kTagSystemWideThresholds)) {
+ IoOveruseAlertThreshold alertThreshold;
+ std::unordered_set<std::string> seenParams;
+ for (const XMLElement* innerElement = outerElement->FirstChildElement(kTagParam);
+ innerElement != nullptr; innerElement = innerElement->NextSiblingElement(kTagParam)) {
+ const char* param = nullptr;
+ if (innerElement->QueryStringAttribute(kAttrId, &param) != XML_SUCCESS) {
+ return Error() << "Failed to read '" << kAttrId << "' attribute in '" << kTagParam
+ << "' tag";
+ }
+ if (seenParams.find(param) != seenParams.end()) {
+ return Error() << "Duplicate threshold specified for param '" << param << "'";
+ }
+ int64_t value = 0;
+ if (const auto text = innerElement->GetText(); text == nullptr) {
+ return Error() << "Must specify non-empty threshold for param '" << param << "'";
+ } else if (const auto valueStr = Trim(text); !ParseInt(valueStr.c_str(), &value)) {
+ return Error() << "Failed to parse threshold for the param '" << param
+ << "': Received threshold value '" << valueStr << "'";
+ }
+ if (!strcmp(param, kParamIdDurationSeconds)) {
+ seenParams.insert(kParamIdDurationSeconds);
+ alertThreshold.durationInSeconds = value;
+ } else if (!strcmp(param, kParamIdWrittenBytesPerSecond)) {
+ seenParams.insert(kParamIdWrittenBytesPerSecond);
+ alertThreshold.writtenBytesPerSecond = value;
+ } else {
+ return Error() << "Invalid param '" << param << "' in I/O overuse alert thresholds";
+ }
+ }
+ if (seenParams.size() != kNumParams) {
+ return Error() << "Thresholds not specified for all params. Specified only for ["
+ << Join(seenParams, ", ") << "] params";
+ }
+ alertThresholds.push_back(alertThreshold);
+ }
+ return alertThresholds;
+}
+
+Result<IoOveruseConfiguration> readIoOveruseConfiguration(ComponentType componentType,
+ const XMLElement* rootElement) {
+ const XMLElement* childElement = nullptr;
+ if (const auto result = readExactlyOneElement(kTagIoOveruseConfiguration, rootElement);
+ result.ok()) {
+ childElement = *result;
+ } else {
+ return Error() << "Failed to read tag '" << kTagIoOveruseConfiguration
+ << "': " << result.error();
+ }
+ IoOveruseConfiguration configuration;
+ if (const auto result = readComponentLevelThresholds(componentType, childElement);
+ result.ok()) {
+ configuration.componentLevelThresholds = *result;
+ } else {
+ return Error() << "Failed to read component-level thresholds: " << result.error();
+ }
+ if (const auto result = readPackageSpecificThresholds(childElement); result.ok()) {
+ configuration.packageSpecificThresholds = *result;
+ } else {
+ return Error() << "Failed to read package specific thresholds: " << result.error();
+ }
+ if (const auto result = readAppCategorySpecificThresholds(childElement); result.ok()) {
+ configuration.categorySpecificThresholds = *result;
+ } else {
+ return Error() << "Failed to read category specific thresholds: " << result.error();
+ }
+ if (const auto result = readSystemWideThresholds(childElement); result.ok()) {
+ configuration.systemWideThresholds = *result;
+ } else {
+ return Error() << "Failed to read system-wide thresholds: " << result.error();
+ }
+ return configuration;
+}
+
+} // namespace
+
+Result<ResourceOveruseConfiguration> OveruseConfigurationXmlHelper::parseXmlFile(
+ const char* filePath) {
+ XMLDocument xmlDoc;
+ xmlDoc.LoadFile(filePath);
+ if (xmlDoc.ErrorID() != XML_SUCCESS) {
+ return Error() << "Failed to read and/or parse '" << filePath << "'";
+ }
+ ResourceOveruseConfiguration configuration;
+ const XMLElement* rootElement = xmlDoc.RootElement();
+ if (!rootElement || strcmp(rootElement->Name(), kTagResourceOveruseConfiguration)) {
+ return Error() << "XML file doesn't have the root element '"
+ << kTagResourceOveruseConfiguration << "'";
+ }
+ if (const auto result = readComponentType(rootElement); result.ok()) {
+ configuration.componentType = *result;
+ } else {
+ return Error() << "Failed to read component type: " << result.error();
+ }
+ if (const auto result = readSafeToKillPackages(rootElement); result.ok()) {
+ configuration.safeToKillPackages = *result;
+ } else {
+ return Error() << "Failed to read safe-to-kill packages: " << result.error();
+ }
+ if (const auto result = readVendorPackagePrefixes(rootElement); result.ok()) {
+ configuration.vendorPackagePrefixes = *result;
+ } else {
+ return Error() << "Failed to read vendor package prefixes: " << result.error();
+ }
+ if (const auto result = readPackageToAppCategoryTypes(rootElement); result.ok()) {
+ configuration.packageMetadata = *result;
+ } else {
+ return Error() << "Failed to read package to app category types: " << result.error();
+ }
+ if (const auto result = readIoOveruseConfiguration(configuration.componentType, rootElement);
+ result.ok()) {
+ configuration.resourceSpecificConfigurations.emplace_back(
+ ResourceSpecificConfiguration(*result));
+ } else {
+ return Error() << "Failed to read I/O overuse configuration: " << result.error();
+ }
+ return configuration;
+}
+
+Result<void> OveruseConfigurationXmlHelper::writeXmlFile(
+ [[maybe_unused]] const ResourceOveruseConfiguration& configuration,
+ [[maybe_unused]] const char* filePath) {
+ // TODO(b/185287136): Write the configuration to file.
+ return {};
+}
+
+} // namespace watchdog
+} // namespace automotive
+} // namespace android
diff --git a/cpp/watchdog/server/src/OveruseConfigurationXmlHelper.h b/cpp/watchdog/server/src/OveruseConfigurationXmlHelper.h
new file mode 100644
index 0000000000..9f501c4c3d
--- /dev/null
+++ b/cpp/watchdog/server/src/OveruseConfigurationXmlHelper.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CPP_WATCHDOG_SERVER_SRC_OVERUSECONFIGURATIONXMLHELPER_H_
+#define CPP_WATCHDOG_SERVER_SRC_OVERUSECONFIGURATIONXMLHELPER_H_
+
+#include <android-base/result.h>
+#include <android/automotive/watchdog/internal/ResourceOveruseConfiguration.h>
+#include <utils/RefBase.h>
+
+namespace android {
+namespace automotive {
+namespace watchdog {
+
+class OveruseConfigurationXmlHelper : public android::RefBase {
+public:
+ static android::base::Result<
+ android::automotive::watchdog::internal::ResourceOveruseConfiguration>
+ parseXmlFile(const char* filePath);
+
+ static android::base::Result<void> writeXmlFile(
+ const android::automotive::watchdog::internal::ResourceOveruseConfiguration&
+ configuration,
+ const char* filePath);
+};
+
+} // namespace watchdog
+} // namespace automotive
+} // namespace android
+
+#endif // CPP_WATCHDOG_SERVER_SRC_OVERUSECONFIGURATIONXMLHELPER_H_
diff --git a/cpp/watchdog/server/tests/IoOveruseConfigsTest.cpp b/cpp/watchdog/server/tests/IoOveruseConfigsTest.cpp
index 433f027a6e..43d08d77ca 100644
--- a/cpp/watchdog/server/tests/IoOveruseConfigsTest.cpp
+++ b/cpp/watchdog/server/tests/IoOveruseConfigsTest.cpp
@@ -15,6 +15,7 @@
*/
#include "IoOveruseConfigs.h"
+#include "OveruseConfigurationTestUtils.h"
#include <android-base/strings.h>
#include <gmock/gmock.h>
@@ -32,41 +33,18 @@ using ::android::automotive::watchdog::internal::IoOveruseAlertThreshold;
using ::android::automotive::watchdog::internal::IoOveruseConfiguration;
using ::android::automotive::watchdog::internal::PackageInfo;
using ::android::automotive::watchdog::internal::PackageMetadata;
-using ::android::automotive::watchdog::internal::PerStateIoOveruseThreshold;
using ::android::automotive::watchdog::internal::ResourceOveruseConfiguration;
using ::android::automotive::watchdog::internal::ResourceSpecificConfiguration;
using ::android::automotive::watchdog::internal::UidType;
using ::android::base::StringAppendF;
using ::android::base::StringPrintf;
-using ::testing::AllOf;
-using ::testing::AnyOf;
-using ::testing::ExplainMatchResult;
-using ::testing::Field;
using ::testing::IsEmpty;
using ::testing::Matcher;
using ::testing::UnorderedElementsAre;
using ::testing::UnorderedElementsAreArray;
-using ::testing::Value;
namespace {
-PerStateBytes toPerStateBytes(const int64_t fgBytes, const int64_t bgBytes,
- const int64_t garageModeBytes) {
- PerStateBytes perStateBytes;
- perStateBytes.foregroundBytes = fgBytes;
- perStateBytes.backgroundBytes = bgBytes;
- perStateBytes.garageModeBytes = garageModeBytes;
- return perStateBytes;
-}
-
-IoOveruseAlertThreshold toIoOveruseAlertThreshold(const int64_t durationInSeconds,
- const int64_t writtenBytesPerSecond) {
- IoOveruseAlertThreshold threshold;
- threshold.durationInSeconds = durationInSeconds;
- threshold.writtenBytesPerSecond = writtenBytesPerSecond;
- return threshold;
-}
-
const PerStateBytes SYSTEM_COMPONENT_LEVEL_THRESHOLDS = toPerStateBytes(200, 100, 500);
const PerStateBytes SYSTEM_PACKAGE_A_THRESHOLDS = toPerStateBytes(600, 400, 1000);
const PerStateBytes SYSTEM_PACKAGE_B_THRESHOLDS = toPerStateBytes(1200, 800, 1500);
@@ -80,43 +58,6 @@ const std::vector<IoOveruseAlertThreshold> ALERT_THRESHOLDS = {toIoOveruseAlertT
toIoOveruseAlertThreshold(30,
40000)};
-PerStateIoOveruseThreshold toPerStateIoOveruseThreshold(const std::string& name,
- const PerStateBytes& perStateBytes) {
- PerStateIoOveruseThreshold threshold;
- threshold.name = name;
- threshold.perStateWriteBytes = perStateBytes;
- return threshold;
-}
-
-PerStateIoOveruseThreshold toPerStateIoOveruseThreshold(const ComponentType type,
- const PerStateBytes& perStateBytes) {
- return toPerStateIoOveruseThreshold(toString(type), perStateBytes);
-}
-
-PerStateIoOveruseThreshold toPerStateIoOveruseThreshold(const std::string& name,
- const int64_t fgBytes,
- const int64_t bgBytes,
- const int64_t garageModeBytes) {
- PerStateIoOveruseThreshold threshold;
- threshold.name = name;
- threshold.perStateWriteBytes = toPerStateBytes(fgBytes, bgBytes, garageModeBytes);
- return threshold;
-}
-
-PerStateIoOveruseThreshold toPerStateIoOveruseThreshold(const ComponentType type,
- const int64_t fgBytes,
- const int64_t bgBytes,
- const int64_t garageModeBytes) {
- return toPerStateIoOveruseThreshold(toString(type), fgBytes, bgBytes, garageModeBytes);
-}
-
-PackageMetadata toPackageMetadata(std::string packageName, ApplicationCategoryType type) {
- PackageMetadata meta;
- meta.packageName = packageName;
- meta.appCategoryType = type;
- return meta;
-}
-
std::unordered_map<std::string, ApplicationCategoryType> toPackageToAppCategoryMappings(
const std::vector<PackageMetadata>& metas) {
std::unordered_map<std::string, ApplicationCategoryType> mappings;
@@ -137,35 +78,6 @@ PackageInfo constructPackageInfo(
return packageInfo;
}
-ResourceOveruseConfiguration constructResourceOveruseConfig(
- const ComponentType type, const std::vector<std::string>&& safeToKill,
- const std::vector<std::string>&& vendorPrefixes,
- const std::vector<PackageMetadata> packageMetadata,
- const IoOveruseConfiguration& ioOveruseConfiguration) {
- ResourceOveruseConfiguration resourceOveruseConfig;
- resourceOveruseConfig.componentType = type;
- resourceOveruseConfig.safeToKillPackages = safeToKill;
- resourceOveruseConfig.vendorPackagePrefixes = vendorPrefixes;
- resourceOveruseConfig.packageMetadata = packageMetadata;
- ResourceSpecificConfiguration config;
- config.set<ResourceSpecificConfiguration::ioOveruseConfiguration>(ioOveruseConfiguration);
- resourceOveruseConfig.resourceSpecificConfigurations.push_back(config);
- return resourceOveruseConfig;
-}
-
-IoOveruseConfiguration constructIoOveruseConfig(
- PerStateIoOveruseThreshold componentLevel,
- const std::vector<PerStateIoOveruseThreshold>& packageSpecific,
- const std::vector<PerStateIoOveruseThreshold>& categorySpecific,
- const std::vector<IoOveruseAlertThreshold>& systemWide) {
- IoOveruseConfiguration config;
- config.componentLevelThresholds = componentLevel;
- config.packageSpecificThresholds = packageSpecific;
- config.categorySpecificThresholds = categorySpecific;
- config.systemWideThresholds = systemWide;
- return config;
-}
-
std::string toString(std::vector<ResourceOveruseConfiguration> configs) {
std::string buffer;
StringAppendF(&buffer, "[");
@@ -179,58 +91,11 @@ std::string toString(std::vector<ResourceOveruseConfiguration> configs) {
return buffer;
}
-MATCHER_P(IsIoOveruseConfiguration, config, "") {
- return arg.componentLevelThresholds == config.componentLevelThresholds &&
- ExplainMatchResult(UnorderedElementsAreArray(config.packageSpecificThresholds),
- arg.packageSpecificThresholds, result_listener) &&
- ExplainMatchResult(UnorderedElementsAreArray(config.categorySpecificThresholds),
- arg.categorySpecificThresholds, result_listener) &&
- ExplainMatchResult(UnorderedElementsAreArray(config.systemWideThresholds),
- arg.systemWideThresholds, result_listener);
-}
-
-MATCHER_P(IsResourceSpecificConfiguration, config, "") {
- if (arg.getTag() != config.getTag()) {
- return false;
- }
- // Reference with the actual datatype so the templated get method can be called.
- const ResourceSpecificConfiguration& expected = config;
- const ResourceSpecificConfiguration& actual = arg;
- switch (arg.getTag()) {
- case ResourceSpecificConfiguration::ioOveruseConfiguration: {
- const auto& expectedIoConfig =
- expected.get<ResourceSpecificConfiguration::ioOveruseConfiguration>();
- const auto& actualIoConfig =
- actual.get<ResourceSpecificConfiguration::ioOveruseConfiguration>();
- return ExplainMatchResult(IsIoOveruseConfiguration(expectedIoConfig), actualIoConfig,
- result_listener);
- }
- default:
- return true;
- }
-}
-
-Matcher<const ResourceOveruseConfiguration> IsResourceOveruseConfiguration(
- const ResourceOveruseConfiguration& config) {
- std::vector<Matcher<const ResourceSpecificConfiguration>> matchers;
- for (const auto& resourceSpecificConfig : config.resourceSpecificConfigurations) {
- matchers.push_back(IsResourceSpecificConfiguration(resourceSpecificConfig));
- }
-
- return AllOf(Field(&ResourceOveruseConfiguration::componentType, config.componentType),
- Field(&ResourceOveruseConfiguration::safeToKillPackages,
- UnorderedElementsAreArray(config.safeToKillPackages)),
- Field(&ResourceOveruseConfiguration::vendorPackagePrefixes,
- UnorderedElementsAreArray(config.vendorPackagePrefixes)),
- Field(&ResourceOveruseConfiguration::resourceSpecificConfigurations,
- UnorderedElementsAreArray(matchers)));
-}
-
-std::vector<Matcher<const ResourceOveruseConfiguration>> IsResourceOveruseConfigurations(
+std::vector<Matcher<const ResourceOveruseConfiguration>> ResourceOveruseConfigurationsMatchers(
const std::vector<ResourceOveruseConfiguration>& configs) {
std::vector<Matcher<const ResourceOveruseConfiguration>> matchers;
for (const auto config : configs) {
- matchers.push_back(IsResourceOveruseConfiguration(config));
+ matchers.push_back(ResourceOveruseConfigurationMatcher(config));
}
return matchers;
}
@@ -313,7 +178,7 @@ TEST(IoOveruseConfigsTest, TestUpdateWithValidConfigs) {
std::vector<ResourceOveruseConfiguration> actual;
ioOveruseConfigs.get(&actual);
- EXPECT_THAT(actual, UnorderedElementsAreArray(IsResourceOveruseConfigurations(expected)))
+ EXPECT_THAT(actual, UnorderedElementsAreArray(ResourceOveruseConfigurationsMatchers(expected)))
<< "Expected: " << toString(expected) << "Actual:" << toString(actual);
// Check whether previous configs are overwritten.
@@ -379,7 +244,7 @@ TEST(IoOveruseConfigsTest, TestUpdateWithValidConfigs) {
actual.clear();
ioOveruseConfigs.get(&actual);
- EXPECT_THAT(actual, UnorderedElementsAreArray(IsResourceOveruseConfigurations(expected)))
+ EXPECT_THAT(actual, UnorderedElementsAreArray(ResourceOveruseConfigurationsMatchers(expected)))
<< "Expected: " << toString(expected) << "Actual:" << toString(actual);
}
@@ -558,7 +423,7 @@ TEST(IoOveruseConfigsTest, TestIgnoresNonUpdatableConfigsBySystemComponent) {
std::vector<ResourceOveruseConfiguration> actual;
ioOveruseConfigs.get(&actual);
- EXPECT_THAT(actual, UnorderedElementsAreArray(IsResourceOveruseConfigurations(expected)))
+ EXPECT_THAT(actual, UnorderedElementsAreArray(ResourceOveruseConfigurationsMatchers(expected)))
<< "Expected: " << toString(expected) << "Actual:" << toString(actual);
}
@@ -597,7 +462,7 @@ TEST(IoOveruseConfigsTest, TestIgnoresNonUpdatableConfigsByVendorComponent) {
std::vector<ResourceOveruseConfiguration> actual;
ioOveruseConfigs.get(&actual);
- EXPECT_THAT(actual, UnorderedElementsAreArray(IsResourceOveruseConfigurations(expected)))
+ EXPECT_THAT(actual, UnorderedElementsAreArray(ResourceOveruseConfigurationsMatchers(expected)))
<< "Expected: " << toString(expected) << "Actual:" << toString(actual);
}
@@ -636,7 +501,7 @@ TEST(IoOveruseConfigsTest, TestIgnoresNonUpdatableConfigsByThirdPartyComponent)
std::vector<ResourceOveruseConfiguration> actual;
ioOveruseConfigs.get(&actual);
- EXPECT_THAT(actual, UnorderedElementsAreArray(IsResourceOveruseConfigurations(expected)))
+ EXPECT_THAT(actual, UnorderedElementsAreArray(ResourceOveruseConfigurationsMatchers(expected)))
<< "Expected: " << toString(expected) << "Actual:" << toString(actual);
}
diff --git a/cpp/watchdog/server/tests/OveruseConfigurationTestUtils.cpp b/cpp/watchdog/server/tests/OveruseConfigurationTestUtils.cpp
new file mode 100644
index 0000000000..ec5908a386
--- /dev/null
+++ b/cpp/watchdog/server/tests/OveruseConfigurationTestUtils.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "OveruseConfigurationTestUtils.h"
+
+namespace android {
+namespace automotive {
+namespace watchdog {
+
+using ::android::automotive::watchdog::internal::ApplicationCategoryType;
+using ::android::automotive::watchdog::internal::ComponentType;
+using ::android::automotive::watchdog::internal::IoOveruseAlertThreshold;
+using ::android::automotive::watchdog::internal::IoOveruseConfiguration;
+using ::android::automotive::watchdog::internal::PackageMetadata;
+using ::android::automotive::watchdog::internal::PerStateIoOveruseThreshold;
+using ::android::automotive::watchdog::internal::ResourceOveruseConfiguration;
+using ::android::automotive::watchdog::internal::ResourceSpecificConfiguration;
+using ::testing::AllOf;
+using ::testing::ExplainMatchResult;
+using ::testing::Field;
+using ::testing::Matcher;
+using ::testing::UnorderedElementsAreArray;
+
+namespace {
+
+MATCHER_P(IsIoOveruseConfiguration, config, "") {
+ return arg.componentLevelThresholds == config.componentLevelThresholds &&
+ ExplainMatchResult(UnorderedElementsAreArray(config.packageSpecificThresholds),
+ arg.packageSpecificThresholds, result_listener) &&
+ ExplainMatchResult(UnorderedElementsAreArray(config.categorySpecificThresholds),
+ arg.categorySpecificThresholds, result_listener) &&
+ ExplainMatchResult(UnorderedElementsAreArray(config.systemWideThresholds),
+ arg.systemWideThresholds, result_listener);
+}
+
+MATCHER_P(IsResourceSpecificConfiguration, config, "") {
+ if (arg.getTag() != config.getTag()) {
+ return false;
+ }
+ // Reference with the actual datatype so the templated get method can be called.
+ const ResourceSpecificConfiguration& expected = config;
+ const ResourceSpecificConfiguration& actual = arg;
+ switch (arg.getTag()) {
+ case ResourceSpecificConfiguration::ioOveruseConfiguration: {
+ const auto& expectedIoConfig =
+ expected.get<ResourceSpecificConfiguration::ioOveruseConfiguration>();
+ const auto& actualIoConfig =
+ actual.get<ResourceSpecificConfiguration::ioOveruseConfiguration>();
+ return ExplainMatchResult(IsIoOveruseConfiguration(expectedIoConfig), actualIoConfig,
+ result_listener);
+ }
+ default:
+ return true;
+ }
+}
+
+} // namespace
+
+ResourceOveruseConfiguration constructResourceOveruseConfig(
+ const ComponentType type, const std::vector<std::string>&& safeToKill,
+ const std::vector<std::string>&& vendorPrefixes,
+ const std::vector<PackageMetadata> packageMetadata,
+ const IoOveruseConfiguration& ioOveruseConfiguration) {
+ ResourceOveruseConfiguration resourceOveruseConfig;
+ resourceOveruseConfig.componentType = type;
+ resourceOveruseConfig.safeToKillPackages = safeToKill;
+ resourceOveruseConfig.vendorPackagePrefixes = vendorPrefixes;
+ resourceOveruseConfig.packageMetadata = packageMetadata;
+ ResourceSpecificConfiguration config;
+ config.set<ResourceSpecificConfiguration::ioOveruseConfiguration>(ioOveruseConfiguration);
+ resourceOveruseConfig.resourceSpecificConfigurations.push_back(config);
+ return resourceOveruseConfig;
+}
+
+IoOveruseConfiguration constructIoOveruseConfig(
+ PerStateIoOveruseThreshold componentLevel,
+ const std::vector<PerStateIoOveruseThreshold>& packageSpecific,
+ const std::vector<PerStateIoOveruseThreshold>& categorySpecific,
+ const std::vector<IoOveruseAlertThreshold>& systemWide) {
+ IoOveruseConfiguration config;
+ config.componentLevelThresholds = componentLevel;
+ config.packageSpecificThresholds = packageSpecific;
+ config.categorySpecificThresholds = categorySpecific;
+ config.systemWideThresholds = systemWide;
+ return config;
+}
+
+PerStateBytes toPerStateBytes(const int64_t fgBytes, const int64_t bgBytes,
+ const int64_t garageModeBytes) {
+ PerStateBytes perStateBytes;
+ perStateBytes.foregroundBytes = fgBytes;
+ perStateBytes.backgroundBytes = bgBytes;
+ perStateBytes.garageModeBytes = garageModeBytes;
+ return perStateBytes;
+}
+
+PerStateIoOveruseThreshold toPerStateIoOveruseThreshold(const std::string& name,
+ const PerStateBytes& perStateBytes) {
+ PerStateIoOveruseThreshold threshold;
+ threshold.name = name;
+ threshold.perStateWriteBytes = perStateBytes;
+ return threshold;
+}
+
+PerStateIoOveruseThreshold toPerStateIoOveruseThreshold(const std::string& name,
+ const int64_t fgBytes,
+ const int64_t bgBytes,
+ const int64_t garageModeBytes) {
+ return toPerStateIoOveruseThreshold(name, toPerStateBytes(fgBytes, bgBytes, garageModeBytes));
+}
+
+PerStateIoOveruseThreshold toPerStateIoOveruseThreshold(const ComponentType type,
+ const PerStateBytes& perStateBytes) {
+ return toPerStateIoOveruseThreshold(toString(type), perStateBytes);
+}
+
+PerStateIoOveruseThreshold toPerStateIoOveruseThreshold(const ComponentType type,
+ const int64_t fgBytes,
+ const int64_t bgBytes,
+ const int64_t garageModeBytes) {
+ return toPerStateIoOveruseThreshold(type, toPerStateBytes(fgBytes, bgBytes, garageModeBytes));
+}
+
+PackageMetadata toPackageMetadata(std::string packageName, ApplicationCategoryType type) {
+ PackageMetadata meta;
+ meta.packageName = packageName;
+ meta.appCategoryType = type;
+ return meta;
+}
+
+IoOveruseAlertThreshold toIoOveruseAlertThreshold(const int64_t durationInSeconds,
+ const int64_t writtenBytesPerSecond) {
+ IoOveruseAlertThreshold threshold;
+ threshold.durationInSeconds = durationInSeconds;
+ threshold.writtenBytesPerSecond = writtenBytesPerSecond;
+ return threshold;
+}
+
+Matcher<const ResourceOveruseConfiguration> ResourceOveruseConfigurationMatcher(
+ const ResourceOveruseConfiguration& config) {
+ std::vector<Matcher<const ResourceSpecificConfiguration>> matchers;
+ for (const auto& resourceSpecificConfig : config.resourceSpecificConfigurations) {
+ matchers.push_back(IsResourceSpecificConfiguration(resourceSpecificConfig));
+ }
+
+ return AllOf(Field(&ResourceOveruseConfiguration::componentType, config.componentType),
+ Field(&ResourceOveruseConfiguration::safeToKillPackages,
+ UnorderedElementsAreArray(config.safeToKillPackages)),
+ Field(&ResourceOveruseConfiguration::vendorPackagePrefixes,
+ UnorderedElementsAreArray(config.vendorPackagePrefixes)),
+ Field(&ResourceOveruseConfiguration::resourceSpecificConfigurations,
+ UnorderedElementsAreArray(matchers)));
+}
+
+} // namespace watchdog
+} // namespace automotive
+} // namespace android
diff --git a/cpp/watchdog/server/tests/OveruseConfigurationTestUtils.h b/cpp/watchdog/server/tests/OveruseConfigurationTestUtils.h
new file mode 100644
index 0000000000..84c970ad2a
--- /dev/null
+++ b/cpp/watchdog/server/tests/OveruseConfigurationTestUtils.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CPP_WATCHDOG_SERVER_TESTS_OVERUSECONFIGURATIONTESTUTILS_H_
+#define CPP_WATCHDOG_SERVER_TESTS_OVERUSECONFIGURATIONTESTUTILS_H_
+
+#include <android/automotive/watchdog/PerStateBytes.h>
+#include <android/automotive/watchdog/internal/ApplicationCategoryType.h>
+#include <android/automotive/watchdog/internal/ComponentType.h>
+#include <android/automotive/watchdog/internal/IoOveruseAlertThreshold.h>
+#include <android/automotive/watchdog/internal/IoOveruseConfiguration.h>
+#include <android/automotive/watchdog/internal/PackageMetadata.h>
+#include <android/automotive/watchdog/internal/PerStateIoOveruseThreshold.h>
+#include <android/automotive/watchdog/internal/ResourceOveruseConfiguration.h>
+#include <gmock/gmock.h>
+
+#include <string>
+#include <vector>
+
+namespace android {
+namespace automotive {
+namespace watchdog {
+
+android::automotive::watchdog::internal::ResourceOveruseConfiguration
+constructResourceOveruseConfig(
+ const android::automotive::watchdog::internal::ComponentType type,
+ const std::vector<std::string>&& safeToKill,
+ const std::vector<std::string>&& vendorPrefixes,
+ const std::vector<android::automotive::watchdog::internal::PackageMetadata> packageMetadata,
+ const android::automotive::watchdog::internal::IoOveruseConfiguration&
+ ioOveruseConfiguration);
+
+android::automotive::watchdog::internal::IoOveruseConfiguration constructIoOveruseConfig(
+ android::automotive::watchdog::internal::PerStateIoOveruseThreshold componentLevel,
+ const std::vector<android::automotive::watchdog::internal::PerStateIoOveruseThreshold>&
+ packageSpecific,
+ const std::vector<android::automotive::watchdog::internal::PerStateIoOveruseThreshold>&
+ categorySpecific,
+ const std::vector<android::automotive::watchdog::internal::IoOveruseAlertThreshold>&
+ systemWide);
+
+PerStateBytes toPerStateBytes(const int64_t fgBytes, const int64_t bgBytes,
+ const int64_t garageModeBytes);
+
+android::automotive::watchdog::internal::PerStateIoOveruseThreshold toPerStateIoOveruseThreshold(
+ const std::string& name, const PerStateBytes& perStateBytes);
+
+android::automotive::watchdog::internal::PerStateIoOveruseThreshold toPerStateIoOveruseThreshold(
+ const std::string& name, const int64_t fgBytes, const int64_t bgBytes,
+ const int64_t garageModeBytes);
+
+android::automotive::watchdog::internal::PerStateIoOveruseThreshold toPerStateIoOveruseThreshold(
+ const android::automotive::watchdog::internal::ComponentType type,
+ const PerStateBytes& perStateBytes);
+
+android::automotive::watchdog::internal::PerStateIoOveruseThreshold toPerStateIoOveruseThreshold(
+ const android::automotive::watchdog::internal::ComponentType type, const int64_t fgBytes,
+ const int64_t bgBytes, const int64_t garageModeBytes);
+
+android::automotive::watchdog::internal::PackageMetadata toPackageMetadata(
+ std::string packageName,
+ android::automotive::watchdog::internal::ApplicationCategoryType type);
+
+android::automotive::watchdog::internal::IoOveruseAlertThreshold toIoOveruseAlertThreshold(
+ const int64_t durationInSeconds, const int64_t writtenBytesPerSecond);
+
+testing::Matcher<const android::automotive::watchdog::internal::ResourceOveruseConfiguration>
+ResourceOveruseConfigurationMatcher(
+ const android::automotive::watchdog::internal::ResourceOveruseConfiguration& config);
+
+} // namespace watchdog
+} // namespace automotive
+} // namespace android
+
+#endif // CPP_WATCHDOG_SERVER_TESTS_OVERUSECONFIGURATIONTESTUTILS_H_
diff --git a/cpp/watchdog/server/tests/OveruseConfigurationXmlHelperTest.cpp b/cpp/watchdog/server/tests/OveruseConfigurationXmlHelperTest.cpp
new file mode 100644
index 0000000000..2595c2bc3b
--- /dev/null
+++ b/cpp/watchdog/server/tests/OveruseConfigurationXmlHelperTest.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "OveruseConfigurationTestUtils.h"
+#include "OveruseConfigurationXmlHelper.h"
+
+#include <android-base/file.h>
+#include <android-base/result.h>
+#include <android/automotive/watchdog/internal/ApplicationCategoryType.h>
+#include <android/automotive/watchdog/internal/ComponentType.h>
+#include <gmock/gmock.h>
+
+namespace android {
+namespace automotive {
+namespace watchdog {
+
+using ::android::automotive::watchdog::internal::ApplicationCategoryType;
+using ::android::automotive::watchdog::internal::ComponentType;
+using ::android::automotive::watchdog::internal::ResourceOveruseConfiguration;
+
+namespace {
+
+constexpr const char* kTestDataDir = "/tests/data/";
+
+constexpr const char* kValidSystemConfiguration = "valid_overuse_system_configuration.xml";
+constexpr const char* kValidVendorConfiguration = "valid_overuse_vendor_configuration.xml";
+constexpr const char* kValidThirdPartyConfiguration = "valid_overuse_third_party_configuration.xml";
+
+const std::vector<const char*> kInvalidOveruseConfigurations =
+ {"duplicate_component_io_thresholds_overuse_configuration.xml",
+ "duplicate_component_type_overuse_configuration.xml",
+ "duplicate_io_config_overuse_configuration.xml",
+ "incomplete_app_category_io_thresholds_overuse_configuration.xml",
+ "incomplete_component_io_thresholds_overuse_configuration.xml",
+ "incomplete_pkg_io_thresholds_overuse_configuration.xml",
+ "incomplete_systemwide_io_thresholds_overuse_configuration.xml",
+ "invalid_component_type_overuse_configuration.xml",
+ "invalid_param_systemwide_io_thresholds_overuse_configuration.xml",
+ "invalid_state_app_category_io_thresholds_overuse_configuration.xml",
+ "invalid_state_component_io_thresholds_overuse_configuration.xml",
+ "invalid_state_pkg_io_thresholds_overuse_configuration.xml",
+ "invalid_type_app_category_mapping_overuse_configuration.xml",
+ "missing_component_io_thresholds_overuse_configuration.xml",
+ "missing_io_config_overuse_configuration.xml",
+ "missing_pkg_name_app_category_mapping_overuse_configuration.xml",
+ "missing_pkg_name_pkg_io_thresholds_overuse_configuration.xml",
+ "missing_pkg_name_safe_to_kill_entry_overuse_configuration.xml",
+ "missing_threshold_app_category_io_thresholds_overuse_configuration.xml",
+ "missing_threshold_component_io_thresholds_overuse_configuration.xml",
+ "missing_threshold_pkg_io_thresholds_overuse_configuration.xml",
+ "missing_threshold_systemwide_io_thresholds_overuse_configuration.xml"};
+
+std::string getTestFilePath(const char* filename) {
+ static std::string baseDir = android::base::GetExecutableDirectory();
+ return baseDir + kTestDataDir + filename;
+}
+
+} // namespace
+
+TEST(OveruseConfigurationXmlHelperTest, TestValidSystemConfiguration) {
+ auto ioConfig = constructIoOveruseConfig(
+ /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::SYSTEM, 300, 150, 500),
+ /*packageSpecific=*/
+ {toPerStateIoOveruseThreshold("system.package.C", 400, 100, 200),
+ toPerStateIoOveruseThreshold("system.package.D", 1024, 500, 2048)},
+ /*categorySpecific=*/{},
+ /*systemWide=*/{toIoOveruseAlertThreshold(10, 200), toIoOveruseAlertThreshold(5, 50)});
+ ResourceOveruseConfiguration expected =
+ constructResourceOveruseConfig(ComponentType::SYSTEM,
+ /*safeToKill=*/{"system.package.A", "system.package.B"},
+ /*vendorPrefixes=*/{},
+ /*packageMetadata=*/
+ {toPackageMetadata("system.package.A",
+ ApplicationCategoryType::MEDIA),
+ toPackageMetadata("system.package.B",
+ ApplicationCategoryType::MAPS)},
+ ioConfig);
+ auto actual = OveruseConfigurationXmlHelper::parseXmlFile(
+ getTestFilePath(kValidSystemConfiguration).c_str());
+ ASSERT_RESULT_OK(actual);
+ EXPECT_THAT(*actual, ResourceOveruseConfigurationMatcher(expected))
+ << "Expected: " << expected.toString() << "\nActual: " << actual->toString();
+}
+
+TEST(OveruseConfigurationXmlHelperTest, TestValidVendorConfiguration) {
+ auto ioConfig = constructIoOveruseConfig(
+ /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::VENDOR, 1024, 512, 3072),
+ /*packageSpecific=*/
+ {toPerStateIoOveruseThreshold("com.vendor.package.C", 400, 100, 200),
+ toPerStateIoOveruseThreshold("com.vendor.package.D", 1024, 500, 2048)},
+ /*categorySpecific=*/
+ {toPerStateIoOveruseThreshold("MAPS", 800, 900, 2048),
+ toPerStateIoOveruseThreshold("MEDIA", 600, 700, 1024)},
+ /*systemWide=*/{});
+ ResourceOveruseConfiguration expected =
+ constructResourceOveruseConfig(ComponentType::VENDOR,
+ /*safeToKill=*/
+ {"com.vendor.package.A", "com.vendor.package.B"},
+ /*vendorPrefixes=*/{"com.vendor.package"},
+ /*packageMetadata=*/
+ {toPackageMetadata("com.vendor.package.A",
+ ApplicationCategoryType::MEDIA),
+ toPackageMetadata("com.vendor.package.B",
+ ApplicationCategoryType::MAPS),
+ toPackageMetadata("com.third.party.package.C",
+ ApplicationCategoryType::MEDIA),
+ toPackageMetadata("system.package.D",
+ ApplicationCategoryType::MAPS)},
+ ioConfig);
+ auto actual = OveruseConfigurationXmlHelper::parseXmlFile(
+ getTestFilePath(kValidVendorConfiguration).c_str());
+ ASSERT_RESULT_OK(actual);
+ EXPECT_THAT(*actual, ResourceOveruseConfigurationMatcher(expected))
+ << "Expected: " << expected.toString() << "\nActual: " << actual->toString();
+}
+
+TEST(OveruseConfigurationXmlHelperTest, TestValidThirdPartyConfiguration) {
+ auto ioConfig = constructIoOveruseConfig(
+ /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::THIRD_PARTY, 300, 150,
+ 500),
+ /*packageSpecific=*/{},
+ /*categorySpecific=*/{},
+ /*systemWide=*/{});
+ ResourceOveruseConfiguration expected =
+ constructResourceOveruseConfig(ComponentType::THIRD_PARTY,
+ /*safeToKill=*/{},
+ /*vendorPrefixes=*/{},
+ /*packageMetadata=*/{}, ioConfig);
+ auto actual = OveruseConfigurationXmlHelper::parseXmlFile(
+ getTestFilePath(kValidThirdPartyConfiguration).c_str());
+ ASSERT_RESULT_OK(actual);
+ EXPECT_THAT(*actual, ResourceOveruseConfigurationMatcher(expected))
+ << "Expected: " << expected.toString() << "\nActual: " << actual->toString();
+}
+
+TEST(OveruseConfigurationXmlHelperTest, TestInvalidOveruseConfigurations) {
+ for (const auto& filename : kInvalidOveruseConfigurations) {
+ ASSERT_FALSE(
+ OveruseConfigurationXmlHelper::parseXmlFile(getTestFilePath(filename).c_str()).ok())
+ << "Must return error on parsing '" << filename << "'";
+ }
+}
+
+} // namespace watchdog
+} // namespace automotive
+} // namespace android
diff --git a/cpp/watchdog/server/tests/data/duplicate_component_io_thresholds_overuse_configuration.xml b/cpp/watchdog/server/tests/data/duplicate_component_io_thresholds_overuse_configuration.xml
new file mode 100644
index 0000000000..9db81290b5
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/duplicate_component_io_thresholds_overuse_configuration.xml
@@ -0,0 +1,31 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> THIRD_PARTY </componentType>
+ <ioOveruseConfiguration>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ </componentLevelThresholds>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ </componentLevelThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration> \ No newline at end of file
diff --git a/cpp/watchdog/server/tests/data/duplicate_component_type_overuse_configuration.xml b/cpp/watchdog/server/tests/data/duplicate_component_type_overuse_configuration.xml
new file mode 100644
index 0000000000..9b04e11114
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/duplicate_component_type_overuse_configuration.xml
@@ -0,0 +1,27 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> THIRD_PARTY </componentType>
+ <ioOveruseConfiguration>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ </componentLevelThresholds>
+ </ioOveruseConfiguration>
+ <componentType> THIRD_PARTY </componentType>
+</resourceOveruseConfiguration> \ No newline at end of file
diff --git a/cpp/watchdog/server/tests/data/duplicate_io_config_overuse_configuration.xml b/cpp/watchdog/server/tests/data/duplicate_io_config_overuse_configuration.xml
new file mode 100644
index 0000000000..5a1b8011c5
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/duplicate_io_config_overuse_configuration.xml
@@ -0,0 +1,33 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> THIRD_PARTY </componentType>
+ <ioOveruseConfiguration>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ </componentLevelThresholds>
+ </ioOveruseConfiguration>
+ <ioOveruseConfiguration>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ </componentLevelThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration> \ No newline at end of file
diff --git a/cpp/watchdog/server/tests/data/incomplete_app_category_io_thresholds_overuse_configuration.xml b/cpp/watchdog/server/tests/data/incomplete_app_category_io_thresholds_overuse_configuration.xml
new file mode 100644
index 0000000000..3de9084901
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/incomplete_app_category_io_thresholds_overuse_configuration.xml
@@ -0,0 +1,34 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> SYSTEM </componentType>
+
+ <ioOveruseConfiguration>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ </componentLevelThresholds>
+
+ <appCategorySpecificThresholds>
+ <appCategoryThreshold id="MEDIA">
+ <state id="foreground_mode"> 600 </state>
+ <state id="background_mode"> 700 </state>
+ </appCategoryThreshold>
+ </appCategorySpecificThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/tests/data/incomplete_component_io_thresholds_overuse_configuration.xml b/cpp/watchdog/server/tests/data/incomplete_component_io_thresholds_overuse_configuration.xml
new file mode 100644
index 0000000000..59f5f2cfc7
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/incomplete_component_io_thresholds_overuse_configuration.xml
@@ -0,0 +1,25 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> THIRD_PARTY </componentType>
+ <ioOveruseConfiguration>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ </componentLevelThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/tests/data/incomplete_pkg_io_thresholds_overuse_configuration.xml b/cpp/watchdog/server/tests/data/incomplete_pkg_io_thresholds_overuse_configuration.xml
new file mode 100644
index 0000000000..abd372ce91
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/incomplete_pkg_io_thresholds_overuse_configuration.xml
@@ -0,0 +1,32 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> SYSTEM </componentType>
+
+ <ioOveruseConfiguration>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ </componentLevelThresholds>
+
+ <packageSpecificThresholds id="system.package.C">
+ <state id="foreground_mode"> 400 </state>
+ <state id="background_mode"> 100 </state>
+ </packageSpecificThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/tests/data/incomplete_systemwide_io_thresholds_overuse_configuration.xml b/cpp/watchdog/server/tests/data/incomplete_systemwide_io_thresholds_overuse_configuration.xml
new file mode 100644
index 0000000000..82332074d0
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/incomplete_systemwide_io_thresholds_overuse_configuration.xml
@@ -0,0 +1,31 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> SYSTEM </componentType>
+
+ <ioOveruseConfiguration>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ </componentLevelThresholds>
+
+ <systemWideThresholds>
+ <param id="written_bytes_per_second"> 200 </param>
+ </systemWideThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/tests/data/invalid_component_type_overuse_configuration.xml b/cpp/watchdog/server/tests/data/invalid_component_type_overuse_configuration.xml
new file mode 100644
index 0000000000..06f351fa53
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/invalid_component_type_overuse_configuration.xml
@@ -0,0 +1,26 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> RANDOM </componentType>
+ <ioOveruseConfiguration>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ </componentLevelThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/tests/data/invalid_param_systemwide_io_thresholds_overuse_configuration.xml b/cpp/watchdog/server/tests/data/invalid_param_systemwide_io_thresholds_overuse_configuration.xml
new file mode 100644
index 0000000000..77f523ef8a
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/invalid_param_systemwide_io_thresholds_overuse_configuration.xml
@@ -0,0 +1,33 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> SYSTEM </componentType>
+
+ <ioOveruseConfiguration>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ </componentLevelThresholds>
+
+ <systemWideThresholds>
+ <param id="duration_seconds"> 10 </param>
+ <param id="written_bytes_per_second"> 200 </param>
+ <param id="random_param"> 200 </param>
+ </systemWideThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/tests/data/invalid_state_app_category_io_thresholds_overuse_configuration.xml b/cpp/watchdog/server/tests/data/invalid_state_app_category_io_thresholds_overuse_configuration.xml
new file mode 100644
index 0000000000..c2f6d6a6f8
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/invalid_state_app_category_io_thresholds_overuse_configuration.xml
@@ -0,0 +1,36 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> SYSTEM </componentType>
+
+ <ioOveruseConfiguration>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ </componentLevelThresholds>
+
+ <appCategorySpecificThresholds>
+ <appCategoryThreshold id="MEDIA">
+ <state id="foreground_mode"> 600 </state>
+ <state id="background_mode"> 700 </state>
+ <state id="garage_mode"> 1024 </state>
+ <state id="random_mode"> 1024 </state>
+ </appCategoryThreshold>
+ </appCategorySpecificThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/tests/data/invalid_state_component_io_thresholds_overuse_configuration.xml b/cpp/watchdog/server/tests/data/invalid_state_component_io_thresholds_overuse_configuration.xml
new file mode 100644
index 0000000000..a86cf54af5
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/invalid_state_component_io_thresholds_overuse_configuration.xml
@@ -0,0 +1,27 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> THIRD_PARTY </componentType>
+ <ioOveruseConfiguration>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ <state id="random_mode"> 500 </state>
+ </componentLevelThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/tests/data/invalid_state_pkg_io_thresholds_overuse_configuration.xml b/cpp/watchdog/server/tests/data/invalid_state_pkg_io_thresholds_overuse_configuration.xml
new file mode 100644
index 0000000000..377b2d72d9
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/invalid_state_pkg_io_thresholds_overuse_configuration.xml
@@ -0,0 +1,34 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> SYSTEM </componentType>
+
+ <ioOveruseConfiguration>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ </componentLevelThresholds>
+
+ <packageSpecificThresholds id="system.package.C">
+ <state id="foreground_mode"> 400 </state>
+ <state id="background_mode"> 100 </state>
+ <state id="garage_mode"> 500 </state>
+ <state id="random_mode"> 500 </state>
+ </packageSpecificThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/tests/data/invalid_type_app_category_mapping_overuse_configuration.xml b/cpp/watchdog/server/tests/data/invalid_type_app_category_mapping_overuse_configuration.xml
new file mode 100644
index 0000000000..412c6d19ea
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/invalid_type_app_category_mapping_overuse_configuration.xml
@@ -0,0 +1,32 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> SYSTEM </componentType>
+
+ <packagesToAppCategoryTypes>
+ <packageAppCategory type="OTHERS"> system.package.A </packageAppCategory>
+ <packageAppCategory type="MAPS"> system.package.B </packageAppCategory>
+ </packagesToAppCategoryTypes>
+
+ <ioOveruseConfiguration>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ </componentLevelThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/tests/data/missing_component_io_thresholds_overuse_configuration.xml b/cpp/watchdog/server/tests/data/missing_component_io_thresholds_overuse_configuration.xml
new file mode 100644
index 0000000000..4fe5fd368b
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/missing_component_io_thresholds_overuse_configuration.xml
@@ -0,0 +1,20 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> THIRD_PARTY </componentType>
+ <ioOveruseConfiguration/>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/tests/data/missing_io_config_overuse_configuration.xml b/cpp/watchdog/server/tests/data/missing_io_config_overuse_configuration.xml
new file mode 100644
index 0000000000..0d286cf908
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/missing_io_config_overuse_configuration.xml
@@ -0,0 +1,19 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> SYSTEM </componentType>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/tests/data/missing_pkg_name_app_category_mapping_overuse_configuration.xml b/cpp/watchdog/server/tests/data/missing_pkg_name_app_category_mapping_overuse_configuration.xml
new file mode 100644
index 0000000000..10b50192eb
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/missing_pkg_name_app_category_mapping_overuse_configuration.xml
@@ -0,0 +1,32 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> SYSTEM </componentType>
+
+ <packagesToAppCategoryTypes>
+ <packageAppCategory type="MEDIA"> </packageAppCategory>
+ <packageAppCategory type="MAPS"> system.package.B </packageAppCategory>
+ </packagesToAppCategoryTypes>
+
+ <ioOveruseConfiguration>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ </componentLevelThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/tests/data/missing_pkg_name_pkg_io_thresholds_overuse_configuration.xml b/cpp/watchdog/server/tests/data/missing_pkg_name_pkg_io_thresholds_overuse_configuration.xml
new file mode 100644
index 0000000000..554f385254
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/missing_pkg_name_pkg_io_thresholds_overuse_configuration.xml
@@ -0,0 +1,33 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> SYSTEM </componentType>
+
+ <ioOveruseConfiguration>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ </componentLevelThresholds>
+
+ <packageSpecificThresholds id="">
+ <state id="foreground_mode"> 400 </state>
+ <state id="background_mode"> 100 </state>
+ <state id="garage_mode"> 200 </state>
+ </packageSpecificThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/tests/data/missing_pkg_name_safe_to_kill_entry_overuse_configuration.xml b/cpp/watchdog/server/tests/data/missing_pkg_name_safe_to_kill_entry_overuse_configuration.xml
new file mode 100644
index 0000000000..a6fdb1d8ad
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/missing_pkg_name_safe_to_kill_entry_overuse_configuration.xml
@@ -0,0 +1,31 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> SYSTEM </componentType>
+
+ <safeToKillPackages>
+ <package/>
+ </safeToKillPackages>
+
+ <ioOveruseConfiguration>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ </componentLevelThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/tests/data/missing_threshold_app_category_io_thresholds_overuse_configuration.xml b/cpp/watchdog/server/tests/data/missing_threshold_app_category_io_thresholds_overuse_configuration.xml
new file mode 100644
index 0000000000..7c264efdfc
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/missing_threshold_app_category_io_thresholds_overuse_configuration.xml
@@ -0,0 +1,35 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> SYSTEM </componentType>
+
+ <ioOveruseConfiguration>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ </componentLevelThresholds>
+
+ <appCategorySpecificThresholds>
+ <appCategoryThreshold id="MEDIA">
+ <state id="foreground_mode"/>
+ <state id="background_mode"> 700 </state>
+ <state id="garage_mode"> 500 </state>
+ </appCategoryThreshold>
+ </appCategorySpecificThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/tests/data/missing_threshold_component_io_thresholds_overuse_configuration.xml b/cpp/watchdog/server/tests/data/missing_threshold_component_io_thresholds_overuse_configuration.xml
new file mode 100644
index 0000000000..dfab25120f
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/missing_threshold_component_io_thresholds_overuse_configuration.xml
@@ -0,0 +1,26 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> THIRD_PARTY </componentType>
+ <ioOveruseConfiguration>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"/>
+ </componentLevelThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/tests/data/missing_threshold_pkg_io_thresholds_overuse_configuration.xml b/cpp/watchdog/server/tests/data/missing_threshold_pkg_io_thresholds_overuse_configuration.xml
new file mode 100644
index 0000000000..89144064be
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/missing_threshold_pkg_io_thresholds_overuse_configuration.xml
@@ -0,0 +1,33 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> SYSTEM </componentType>
+
+ <ioOveruseConfiguration>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ </componentLevelThresholds>
+
+ <packageSpecificThresholds id="system.package.C">
+ <state id="foreground_mode"> 400 </state>
+ <state id="background_mode"/>
+ <state id="garage_mode"> 100 </state>
+ </packageSpecificThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/tests/data/missing_threshold_systemwide_io_thresholds_overuse_configuration.xml b/cpp/watchdog/server/tests/data/missing_threshold_systemwide_io_thresholds_overuse_configuration.xml
new file mode 100644
index 0000000000..0341c06698
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/missing_threshold_systemwide_io_thresholds_overuse_configuration.xml
@@ -0,0 +1,32 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> SYSTEM </componentType>
+
+ <ioOveruseConfiguration>
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ </componentLevelThresholds>
+
+ <systemWideThresholds>
+ <param id="duration_seconds"> 10 </param>
+ <param id="written_bytes_per_second"/>
+ </systemWideThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/tests/data/valid_overuse_system_configuration.xml b/cpp/watchdog/server/tests/data/valid_overuse_system_configuration.xml
new file mode 100644
index 0000000000..854abc7e00
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/valid_overuse_system_configuration.xml
@@ -0,0 +1,64 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> SYSTEM </componentType>
+
+ <!-- List of safe to kill system packages. -->
+ <safeToKillPackages>
+ <package> system.package.A </package>
+ <package> system.package.B </package>
+ </safeToKillPackages>
+
+ <!-- List of unique package names to app category mappings. -->
+ <packagesToAppCategoryTypes>
+ <packageAppCategory type="MEDIA"> system.package.A </packageAppCategory>
+ <packageAppCategory type="MAPS"> system.package.B </packageAppCategory>
+ </packagesToAppCategoryTypes>
+
+ <ioOveruseConfiguration>
+ <!-- Thresholds in MiB for all system packages that don’t have package specific thresholds. -->
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ </componentLevelThresholds>
+
+ <!-- Package specific thresholds. -->
+ <packageSpecificThresholds id="system.package.C">
+ <state id="foreground_mode"> 400 </state>
+ <state id="background_mode"> 100 </state>
+ <state id="garage_mode"> 200 </state>
+ </packageSpecificThresholds>
+
+ <packageSpecificThresholds id="system.package.D">
+ <state id="foreground_mode"> 1024 </state>
+ <state id="background_mode"> 500 </state>
+ <state id="garage_mode"> 2048 </state>
+ </packageSpecificThresholds>
+
+ <!-- List of system-wide disk I/O overuse alert thresholds. -->
+ <systemWideThresholds>
+ <param id="duration_seconds"> 10 </param>
+ <param id="written_bytes_per_second"> 200 </param>
+ </systemWideThresholds>
+
+ <systemWideThresholds>
+ <param id="duration_seconds"> 5 </param>
+ <param id="written_bytes_per_second"> 50 </param>
+ </systemWideThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/tests/data/valid_overuse_third_party_configuration.xml b/cpp/watchdog/server/tests/data/valid_overuse_third_party_configuration.xml
new file mode 100644
index 0000000000..b3bacb60e5
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/valid_overuse_third_party_configuration.xml
@@ -0,0 +1,27 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> THIRD_PARTY </componentType>
+ <ioOveruseConfiguration>
+ <!-- Thresholds in MiB for all third-party packages. -->
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 300 </state>
+ <state id="background_mode"> 150 </state>
+ <state id="garage_mode"> 500 </state>
+ </componentLevelThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration> \ No newline at end of file
diff --git a/cpp/watchdog/server/tests/data/valid_overuse_vendor_configuration.xml b/cpp/watchdog/server/tests/data/valid_overuse_vendor_configuration.xml
new file mode 100644
index 0000000000..b7b43417b3
--- /dev/null
+++ b/cpp/watchdog/server/tests/data/valid_overuse_vendor_configuration.xml
@@ -0,0 +1,75 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resourceOveruseConfiguration version="1.0">
+ <componentType> VENDOR </componentType>
+
+ <!-- List of safe to kill system packages. -->
+ <safeToKillPackages>
+ <package> com.vendor.package.A </package>
+ <package> com.vendor.package.B </package>
+ </safeToKillPackages>
+
+ <!-- List of vendor package prefixes. -->
+ <vendorPackagePrefixes>
+ <packagePrefix> com.vendor.package </packagePrefix>
+ </vendorPackagePrefixes>
+
+ <!-- List of unique package names to app category mappings. -->
+ <packagesToAppCategoryTypes>
+ <packageAppCategory type="MEDIA"> com.vendor.package.A </packageAppCategory>
+ <packageAppCategory type="MAPS"> com.vendor.package.B </packageAppCategory>
+ <packageAppCategory type="MEDIA"> com.third.party.package.C </packageAppCategory>
+ <packageAppCategory type="MAPS"> system.package.D </packageAppCategory>
+ </packagesToAppCategoryTypes>
+
+ <ioOveruseConfiguration>
+ <!-- Thresholds in MiB for all vendor packages that don’t have package specific thresholds. -->
+ <componentLevelThresholds>
+ <state id="foreground_mode"> 1024 </state>
+ <state id="background_mode"> 512 </state>
+ <state id="garage_mode"> 3072 </state>
+ </componentLevelThresholds>
+
+ <!-- Package specific thresholds. -->
+ <packageSpecificThresholds id="com.vendor.package.C">
+ <state id="foreground_mode"> 400 </state>
+ <state id="background_mode"> 100 </state>
+ <state id="garage_mode"> 200 </state>
+ </packageSpecificThresholds>
+
+ <packageSpecificThresholds id="com.vendor.package.D">
+ <state id="foreground_mode"> 1024 </state>
+ <state id="background_mode"> 500 </state>
+ <state id="garage_mode"> 2048 </state>
+ </packageSpecificThresholds>
+
+ <!-- Application category specific thresholds. -->
+ <appCategorySpecificThresholds>
+ <appCategoryThreshold id="MEDIA">
+ <state id="foreground_mode"> 600 </state>
+ <state id="background_mode"> 700 </state>
+ <state id="garage_mode"> 1024 </state>
+ </appCategoryThreshold>
+
+ <appCategoryThreshold id="MAPS">
+ <state id="foreground_mode"> 800 </state>
+ <state id="background_mode"> 900 </state>
+ <state id="garage_mode"> 2048 </state>
+ </appCategoryThreshold>
+ </appCategorySpecificThresholds>
+ </ioOveruseConfiguration>
+</resourceOveruseConfiguration>