Read the on-device XML configurations on initialization.

Update watchdog daemon to read the on-device resource overuse
configurations, that are stored as XML files, on initialization.

When latest configs are available under the data partition, watchdog
daemon uses the latest configs. Otherwise, the XML configurations from
the build are used. If all of these fail, watchdog daemon fallbacks to
using int max as the default thresholds.

When either of the vendor or third-party configurations aren't
available, watchdog daemon uses the system component's thresholds for
the vendor or third-party components.

Test: atest libwatchdog_test
Bug: 186445673

Change-Id: I94e08d618ff0cd164aadf4d37eae93e19b2dae67
diff --git a/cpp/watchdog/server/Android.bp b/cpp/watchdog/server/Android.bp
index 9b5b973..8ce4c04 100644
--- a/cpp/watchdog/server/Android.bp
+++ b/cpp/watchdog/server/Android.bp
@@ -200,4 +200,20 @@
       "libwatchdog_package_info_resolver",
     ],
     vintf_fragments: ["carwatchdogd.xml"],
+    required: [
+        "system_resource_overuse_configuration.xml",
+        "third_party_resource_overuse_configuration.xml",
+    ],
+}
+
+prebuilt_etc {
+    name: "system_resource_overuse_configuration.xml",
+    src: "data/system_resource_overuse_configuration.xml",
+    sub_dir: "automotive/watchdog/",
+}
+
+prebuilt_etc {
+    name: "third_party_resource_overuse_configuration.xml",
+    src: "data/third_party_resource_overuse_configuration.xml",
+    sub_dir: "automotive/watchdog/",
 }
diff --git a/cpp/watchdog/server/data/system_resource_overuse_configuration.xml b/cpp/watchdog/server/data/system_resource_overuse_configuration.xml
new file mode 100644
index 0000000..e04e17f
--- /dev/null
+++ b/cpp/watchdog/server/data/system_resource_overuse_configuration.xml
@@ -0,0 +1,55 @@
+<?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> shared:com.google.android.car.uid.kitchensink </package>
+  </safeToKillPackages>
+
+  <ioOveruseConfiguration>
+    <!-- Default thresholds in MiB for all system packages that don’t have package specific
+         thresholds or app category specific thresholds. -->
+    <componentLevelThresholds>
+      <state id="foreground_mode"> 3072 </state>
+      <state id="background_mode"> 2048 </state>
+      <state id="garage_mode"> 4096 </state>
+    </componentLevelThresholds>
+
+    <!-- Package specific thresholds. -->
+    <!-- Kitchensink app tests package warning/killing on overuse and requires less threshold so it
+         can test the implementation with less amount of writes. However, it shouldn't be killed
+         often when running other tests.-->
+    <packageSpecificThresholds id="shared:com.google.android.car.uid.kitchensink">
+      <state id="foreground_mode"> 512 </state>
+      <state id="background_mode"> 512 </state>
+      <state id="garage_mode"> 512 </state>
+    </packageSpecificThresholds>
+
+    <!-- List of system-wide disk I/O overuse alert thresholds. -->
+    <systemWideThresholds>
+      <!-- 1GiB written in 30 seconds -->
+      <param id="duration_seconds"> 30 </param>
+      <param id="written_bytes_per_second"> 35791394 </param>
+    </systemWideThresholds>
+    <systemWideThresholds>
+      <!-- 500MiB written in 10 seconds -->
+      <param id="duration_seconds"> 10 </param>
+      <param id="written_bytes_per_second"> 52428800 </param>
+    </systemWideThresholds>
+  </ioOveruseConfiguration>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/data/third_party_resource_overuse_configuration.xml b/cpp/watchdog/server/data/third_party_resource_overuse_configuration.xml
new file mode 100644
index 0000000..ee17b60
--- /dev/null
+++ b/cpp/watchdog/server/data/third_party_resource_overuse_configuration.xml
@@ -0,0 +1,28 @@
+<?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>
+    <!-- Default thresholds in MiB for all third-party packages that don't have app category
+         specific thresholds. -->
+    <componentLevelThresholds>
+      <state id="foreground_mode"> 3072 </state>
+      <state id="background_mode"> 2048 </state>
+      <state id="garage_mode"> 4096 </state>
+    </componentLevelThresholds>
+  </ioOveruseConfiguration>
+</resourceOveruseConfiguration>
diff --git a/cpp/watchdog/server/src/IoOveruseConfigs.cpp b/cpp/watchdog/server/src/IoOveruseConfigs.cpp
index 90a73df..ca49c1b 100644
--- a/cpp/watchdog/server/src/IoOveruseConfigs.cpp
+++ b/cpp/watchdog/server/src/IoOveruseConfigs.cpp
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2020, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,12 +18,15 @@
 
 #include "IoOveruseConfigs.h"
 
+#include "OveruseConfigurationXmlHelper.h"
 #include "PackageInfoResolver.h"
 
 #include <android-base/strings.h>
+#include <log/log.h>
 
 #include <inttypes.h>
 
+#include <filesystem>
 #include <limits>
 
 namespace android {
@@ -180,7 +183,46 @@
     }
 }
 
-Result<void> isValidConfigs(
+Result<void> isValidResourceOveruseConfig(
+        const ResourceOveruseConfiguration& resourceOveruseConfig) {
+    const auto filter = getComponentFilter(resourceOveruseConfig.componentType);
+    if (!filter.ok()) {
+        return Error() << filter.error();
+    }
+    std::unordered_map<std::string, ApplicationCategoryType> seenCategoryMappings;
+    for (const auto& meta : resourceOveruseConfig.packageMetadata) {
+        if (const auto it = seenCategoryMappings.find(meta.packageName);
+            it != seenCategoryMappings.end() && it->second != meta.appCategoryType) {
+            return Error()
+                    << "Must provide exactly one application category mapping for the package "
+                    << meta.packageName << ": Provided mappings " << toString(meta.appCategoryType)
+                    << " and " << toString(it->second);
+        }
+        seenCategoryMappings[meta.packageName] = meta.appCategoryType;
+    }
+    if (resourceOveruseConfig.resourceSpecificConfigurations.size() != 1) {
+        return Error() << "Must provide exactly one I/O overuse configuration. Received "
+                       << resourceOveruseConfig.resourceSpecificConfigurations.size()
+                       << " configurations";
+    }
+    for (const auto& config : resourceOveruseConfig.resourceSpecificConfigurations) {
+        if (config.getTag() != ResourceSpecificConfiguration::ioOveruseConfiguration) {
+            return Error() << "Invalid resource type: " << config.getTag();
+        }
+        const auto& ioOveruseConfig =
+                config.get<ResourceSpecificConfiguration::ioOveruseConfiguration>();
+        if (auto result = isValidIoOveruseConfiguration(resourceOveruseConfig.componentType,
+                                                        *filter, ioOveruseConfig);
+            !result.ok()) {
+            return Error() << "Invalid I/O overuse configuration for component "
+                           << toString(resourceOveruseConfig.componentType).c_str() << ": "
+                           << result.error();
+        }
+    }
+    return {};
+}
+
+Result<void> isValidResourceOveruseConfigs(
         const std::vector<ResourceOveruseConfiguration>& resourceOveruseConfigs) {
     std::unordered_set<ComponentType> seenComponentTypes;
     for (const auto& resourceOveruseConfig : resourceOveruseConfigs) {
@@ -188,36 +230,19 @@
             return Error() << "Cannot provide duplicate configs for the same component type "
                            << toString(resourceOveruseConfig.componentType);
         }
-        const auto filter = getComponentFilter(resourceOveruseConfig.componentType);
-        if (!filter.ok()) {
-            return Error() << filter.error();
+        if (const auto result = isValidResourceOveruseConfig(resourceOveruseConfig); !result.ok()) {
+            return result;
         }
         seenComponentTypes.insert(resourceOveruseConfig.componentType);
-        if (resourceOveruseConfig.resourceSpecificConfigurations.size() != 1) {
-            return Error() << "Must provide exactly one I/O overuse configuration. Received "
-                           << resourceOveruseConfig.resourceSpecificConfigurations.size()
-                           << " configurations";
-        }
-        for (const auto& config : resourceOveruseConfig.resourceSpecificConfigurations) {
-            if (config.getTag() != ResourceSpecificConfiguration::ioOveruseConfiguration) {
-                return Error() << "Invalid resource type: " << config.getTag();
-            }
-            const auto& ioOveruseConfig =
-                    config.get<ResourceSpecificConfiguration::ioOveruseConfiguration>();
-            if (auto result = isValidIoOveruseConfiguration(resourceOveruseConfig.componentType,
-                                                            *filter, ioOveruseConfig);
-                !result.ok()) {
-                return Error() << "Invalid config for component "
-                               << toString(resourceOveruseConfig.componentType).c_str()
-                               << result.error();
-            }
-        }
     }
     return {};
 }
 
 }  // namespace
 
+IoOveruseConfigs::ParseXmlFileFunction IoOveruseConfigs::sParseXmlFile =
+        &OveruseConfigurationXmlHelper::parseXmlFile;
+
 Result<void> ComponentSpecificConfig::updatePerPackageThresholds(
         const std::vector<PerStateIoOveruseThreshold>& thresholds,
         const std::function<void(const std::string&)>& maybeAppendVendorPackagePrefixes) {
@@ -234,7 +259,7 @@
         maybeAppendVendorPackagePrefixes(packageThreshold.name);
         if (auto result = containsValidThresholds(packageThreshold); !result.ok()) {
             StringAppendF(&errorMsgs,
-                          "\tSkipping invalid package specific thresholds for package %s: %s\n",
+                          "\tSkipping invalid package specific thresholds for package '%s': %s\n",
                           packageThreshold.name.c_str(), result.error().message().c_str());
             continue;
         }
@@ -267,6 +292,54 @@
     return errorMsgs.empty() ? Result<void>{} : Error() << errorMsgs;
 }
 
+IoOveruseConfigs::IoOveruseConfigs() :
+      mSystemConfig({}),
+      mVendorConfig({}),
+      mThirdPartyConfig({}),
+      mPackagesToAppCategories({}),
+      mPackagesToAppCategoryMappingUpdateMode(OVERWRITE),
+      mPerCategoryThresholds({}),
+      mVendorPackagePrefixes({}) {
+    const auto updateFromXmlPerType = [&](const char* filename, const char* configType) -> bool {
+        if (const auto result = this->updateFromXml(filename); !result.ok()) {
+            ALOGE("Failed to parse %s resource overuse configuration from '%s': %s", configType,
+                  filename, result.error().message().c_str());
+            return false;
+        }
+        ALOGI("Updated with %s resource overuse configuration from '%s'", configType, filename);
+        return true;
+    };
+    /*
+     * Package to app category mapping is common between system and vendor component configs. When
+     * the build system and vendor component configs are used, the mapping shouldn't be
+     * overwritten by either of the configs because the build configurations defined by the
+     * vendor or system components may not be aware of mappings included in other component's
+     * config. Ergo, the mapping from both the component configs should be merged together. When a
+     * latest config is used for either of the components, the latest mapping should be given higher
+     * priority.
+     */
+    bool isBuildSystemConfig = false;
+    if (!updateFromXmlPerType(kLatestSystemConfigXmlPath, "latest system")) {
+        isBuildSystemConfig = updateFromXmlPerType(kBuildSystemConfigXmlPath, "build system");
+    }
+    if (!updateFromXmlPerType(kLatestVendorConfigXmlPath, "latest vendor")) {
+        mPackagesToAppCategoryMappingUpdateMode = isBuildSystemConfig ? MERGE : NO_UPDATE;
+        if (!updateFromXmlPerType(kBuildVendorConfigXmlPath, "build vendor") &&
+            mSystemConfig.mGeneric.name != kDefaultThresholdName) {
+            mVendorConfig.mGeneric = mSystemConfig.mGeneric;
+            mVendorConfig.mGeneric.name = toString(ComponentType::VENDOR);
+        }
+        mPackagesToAppCategoryMappingUpdateMode = OVERWRITE;
+    }
+    if (!updateFromXmlPerType(kLatestThirdPartyConfigXmlPath, "latest third-party")) {
+        if (!updateFromXmlPerType(kBuildThirdPartyConfigXmlPath, "build third-party") &&
+            mSystemConfig.mGeneric.name != kDefaultThresholdName) {
+            mThirdPartyConfig.mGeneric = mSystemConfig.mGeneric;
+            mThirdPartyConfig.mGeneric.name = toString(ComponentType::THIRD_PARTY);
+        }
+    }
+}
+
 size_t IoOveruseConfigs::AlertThresholdHashByDuration::operator()(
         const IoOveruseAlertThreshold& threshold) const {
     return std::hash<std::string>{}(std::to_string(threshold.durationInSeconds));
@@ -286,13 +359,13 @@
     std::string errorMsgs;
     for (const auto& categoryThreshold : thresholds) {
         if (auto result = containsValidThresholds(categoryThreshold); !result.ok()) {
-            StringAppendF(&errorMsgs, "\tInvalid category specific thresholds: %s\n",
+            StringAppendF(&errorMsgs, "\tInvalid category specific thresholds: '%s'\n",
                           result.error().message().c_str());
             continue;
         }
         if (auto category = toApplicationCategoryType(categoryThreshold.name);
             category == ApplicationCategoryType::OTHERS) {
-            StringAppendF(&errorMsgs, "\tInvalid application category %s\n",
+            StringAppendF(&errorMsgs, "\tInvalid application category '%s'\n",
                           categoryThreshold.name.c_str());
         } else {
             if (const auto& it = mPerCategoryThresholds.find(category);
@@ -330,52 +403,68 @@
 
 Result<void> IoOveruseConfigs::update(
         const std::vector<ResourceOveruseConfiguration>& resourceOveruseConfigs) {
-    if (auto result = isValidConfigs(resourceOveruseConfigs); !result.ok()) {
+    if (const auto result = isValidResourceOveruseConfigs(resourceOveruseConfigs); !result.ok()) {
         return Error(Status::EX_ILLEGAL_ARGUMENT) << result.error();
     }
-
     for (const auto& resourceOveruseConfig : resourceOveruseConfigs) {
-        ComponentSpecificConfig* targetComponentConfig;
-        int32_t updatableConfigsFilter = 0;
-        switch (resourceOveruseConfig.componentType) {
-            case ComponentType::SYSTEM:
-                targetComponentConfig = &mSystemConfig;
-                updatableConfigsFilter = kSystemComponentUpdatableConfigs;
-                break;
-            case ComponentType::VENDOR:
-                targetComponentConfig = &mVendorConfig;
-                updatableConfigsFilter = kVendorComponentUpdatableConfigs;
-                break;
-            case ComponentType::THIRD_PARTY:
-                targetComponentConfig = &mThirdPartyConfig;
-                updatableConfigsFilter = kThirdPartyComponentUpdatableConfigs;
-                break;
-            default:
-                // This case shouldn't execute as it is caught during validation.
-                continue;
-        }
-
-        const std::string componentTypeStr = toString(resourceOveruseConfig.componentType);
-        for (const auto& resourceSpecificConfig :
-             resourceOveruseConfig.resourceSpecificConfigurations) {
-            /*
-             * |resourceSpecificConfig| should contain only ioOveruseConfiguration as it is verified
-             * during validation.
-             */
-            const auto& ioOveruseConfig =
-                    resourceSpecificConfig
-                            .get<ResourceSpecificConfiguration::ioOveruseConfiguration>();
-            if (auto res = update(resourceOveruseConfig, ioOveruseConfig, updatableConfigsFilter,
-                                  targetComponentConfig);
-                !res.ok()) {
-                ALOGE("Invalid I/O overuse configurations received for %s component:\n%s",
-                      componentTypeStr.c_str(), res.error().message().c_str());
-            }
-        }
+        updateFromAidlConfig(resourceOveruseConfig);
     }
     return {};
 }
 
+Result<void> IoOveruseConfigs::updateFromXml(const char* filename) {
+    const auto resourceOveruseConfig = sParseXmlFile(filename);
+    if (!resourceOveruseConfig.ok()) {
+        return Error() << "Failed to parse configuration: " << resourceOveruseConfig.error();
+    }
+    if (const auto result = isValidResourceOveruseConfig(*resourceOveruseConfig); !result.ok()) {
+        return result;
+    }
+    updateFromAidlConfig(*resourceOveruseConfig);
+    return {};
+}
+
+void IoOveruseConfigs::updateFromAidlConfig(
+        const ResourceOveruseConfiguration& resourceOveruseConfig) {
+    ComponentSpecificConfig* targetComponentConfig;
+    int32_t updatableConfigsFilter = 0;
+    switch (resourceOveruseConfig.componentType) {
+        case ComponentType::SYSTEM:
+            targetComponentConfig = &mSystemConfig;
+            updatableConfigsFilter = kSystemComponentUpdatableConfigs;
+            break;
+        case ComponentType::VENDOR:
+            targetComponentConfig = &mVendorConfig;
+            updatableConfigsFilter = kVendorComponentUpdatableConfigs;
+            break;
+        case ComponentType::THIRD_PARTY:
+            targetComponentConfig = &mThirdPartyConfig;
+            updatableConfigsFilter = kThirdPartyComponentUpdatableConfigs;
+            break;
+        default:
+            // This case shouldn't execute as it is caught during validation.
+            return;
+    }
+
+    const std::string componentTypeStr = toString(resourceOveruseConfig.componentType);
+    for (const auto& resourceSpecificConfig :
+         resourceOveruseConfig.resourceSpecificConfigurations) {
+        /*
+         * |resourceSpecificConfig| should contain only ioOveruseConfiguration as it is verified
+         * during validation.
+         */
+        const auto& ioOveruseConfig =
+                resourceSpecificConfig.get<ResourceSpecificConfiguration::ioOveruseConfiguration>();
+        if (auto res = update(resourceOveruseConfig, ioOveruseConfig, updatableConfigsFilter,
+                              targetComponentConfig);
+            !res.ok()) {
+            ALOGE("Ignorable I/O overuse configuration errors for '%s' component:\n%s",
+                  componentTypeStr.c_str(), res.error().message().c_str());
+        }
+    }
+    return;
+}
+
 Result<void> IoOveruseConfigs::update(
         const ResourceOveruseConfiguration& resourceOveruseConfiguration,
         const IoOveruseConfiguration& ioOveruseConfiguration, int32_t updatableConfigsFilter,
@@ -398,10 +487,14 @@
     }
 
     if (updatableConfigsFilter & OveruseConfigEnum::PACKAGE_APP_CATEGORY_MAPPINGS) {
-        mPackagesToAppCategories.clear();
-        for (const auto& meta : resourceOveruseConfiguration.packageMetadata) {
-            if (!meta.packageName.empty()) {
-                mPackagesToAppCategories[meta.packageName] = meta.appCategoryType;
+        if (mPackagesToAppCategoryMappingUpdateMode == OVERWRITE) {
+            mPackagesToAppCategories.clear();
+        }
+        if (mPackagesToAppCategoryMappingUpdateMode != NO_UPDATE) {
+            for (const auto& meta : resourceOveruseConfiguration.packageMetadata) {
+                if (!meta.packageName.empty()) {
+                    mPackagesToAppCategories[meta.packageName] = meta.appCategoryType;
+                }
             }
         }
     } else if (!resourceOveruseConfiguration.packageMetadata.empty()) {
@@ -430,7 +523,7 @@
                                                                        .packageSpecificThresholds,
                                                                maybeAppendVendorPackagePrefixes);
             !result.ok()) {
-            StringAppendF(&errorMsgs, "%s", result.error().message().c_str());
+            StringAppendF(&errorMsgs, "\t\t%s", result.error().message().c_str());
         }
     } else if (!ioOveruseConfiguration.packageSpecificThresholds.empty()) {
         StringAppendF(&nonUpdatableConfigMsgs, "%sper-package thresholds",
@@ -443,7 +536,8 @@
                                                                      .safeToKillPackages,
                                                              maybeAppendVendorPackagePrefixes);
             !result.ok()) {
-            StringAppendF(&errorMsgs, "%s", result.error().message().c_str());
+            StringAppendF(&errorMsgs, "%s\t\t%s", !errorMsgs.empty() ? "\n" : "",
+                          result.error().message().c_str());
         }
     } else if (!resourceOveruseConfiguration.safeToKillPackages.empty()) {
         StringAppendF(&nonUpdatableConfigMsgs, "%ssafe-to-kill list",
@@ -454,7 +548,8 @@
         if (auto result =
                     updatePerCategoryThresholds(ioOveruseConfiguration.categorySpecificThresholds);
             !result.ok()) {
-            StringAppendF(&errorMsgs, "%s", result.error().message().c_str());
+            StringAppendF(&errorMsgs, "%s\t\t%s", !errorMsgs.empty() ? "\n" : "",
+                          result.error().message().c_str());
         }
     } else if (!ioOveruseConfiguration.categorySpecificThresholds.empty()) {
         StringAppendF(&nonUpdatableConfigMsgs, "%scategory specific thresholds",
@@ -464,7 +559,8 @@
     if (updatableConfigsFilter & OveruseConfigEnum::SYSTEM_WIDE_ALERT_THRESHOLDS) {
         if (auto result = updateAlertThresholds(ioOveruseConfiguration.systemWideThresholds);
             !result.ok()) {
-            StringAppendF(&errorMsgs, "%s", result.error().message().c_str());
+            StringAppendF(&errorMsgs, "%s\t\t%s", !errorMsgs.empty() ? "\n" : "",
+                          result.error().message().c_str());
         }
     } else if (!ioOveruseConfiguration.systemWideThresholds.empty()) {
         StringAppendF(&nonUpdatableConfigMsgs, "%ssystem-wide alert thresholds",
@@ -472,8 +568,8 @@
     }
 
     if (!nonUpdatableConfigMsgs.empty()) {
-        StringAppendF(&errorMsgs, "\tReceived values for non-updatable configs: %s\n",
-                      nonUpdatableConfigMsgs.c_str());
+        StringAppendF(&errorMsgs, "%s\t\tReceived values for non-updatable configs: [%s]",
+                      !errorMsgs.empty() ? "\n" : "", nonUpdatableConfigMsgs.c_str());
     }
     if (!errorMsgs.empty()) {
         return Error() << errorMsgs.c_str();
diff --git a/cpp/watchdog/server/src/IoOveruseConfigs.h b/cpp/watchdog/server/src/IoOveruseConfigs.h
index e0a2435..ad7c3ac 100644
--- a/cpp/watchdog/server/src/IoOveruseConfigs.h
+++ b/cpp/watchdog/server/src/IoOveruseConfigs.h
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2020, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -32,11 +32,24 @@
 #include <string_view>
 #include <unordered_map>
 #include <unordered_set>
+#include <vector>
 
 namespace android {
 namespace automotive {
 namespace watchdog {
-constexpr const char* kDefaultThresholdName = "default";
+constexpr const char kBuildSystemConfigXmlPath[] =
+        "/system/etc/automotive/watchdog/system_resource_overuse_configuration.xml";
+constexpr const char kBuildThirdPartyConfigXmlPath[] =
+        "/system/etc/automotive/watchdog/third_party_resource_overuse_configuration.xml";
+constexpr const char kBuildVendorConfigXmlPath[] =
+        "/vendor/etc/automotive/watchdog/resource_overuse_configuration.xml";
+constexpr const char kLatestSystemConfigXmlPath[] =
+        "/data/system/car/watchdog/system_resource_overuse_configuration.xml";
+constexpr const char kLatestVendorConfigXmlPath[] =
+        "/data/system/car/watchdog/vendor_resource_overuse_configuration.xml";
+constexpr const char kLatestThirdPartyConfigXmlPath[] =
+        "/data/system/car/watchdog/third_party_resource_overuse_configuration.xml";
+constexpr const char kDefaultThresholdName[] = "default";
 
 inline const android::automotive::watchdog::internal::PerStateIoOveruseThreshold
 defaultThreshold() {
@@ -48,6 +61,13 @@
     return threshold;
 }
 
+// Forward declaration for testing use only.
+namespace internal {
+
+class IoOveruseConfigsPeer;
+
+}  // namespace internal
+
 /*
  * Defines the methods that the I/O overuse configs module should implement.
  */
@@ -159,7 +179,7 @@
  */
 class IoOveruseConfigs final : public IIoOveruseConfigs {
 public:
-    IoOveruseConfigs() {}
+    IoOveruseConfigs();
     ~IoOveruseConfigs() {
         mPerCategoryThresholds.clear();
         mVendorPackagePrefixes.clear();
@@ -168,30 +188,43 @@
 
     android::base::Result<void>
     update(const std::vector<android::automotive::watchdog::internal::ResourceOveruseConfiguration>&
-                   configs);
+                   configs) override;
 
     void get(std::vector<android::automotive::watchdog::internal::ResourceOveruseConfiguration>*
-                     resourceOveruseConfigs);
+                     resourceOveruseConfigs) override;
 
     PerStateBytes fetchThreshold(
-            const android::automotive::watchdog::internal::PackageInfo& packageInfo) const;
+            const android::automotive::watchdog::internal::PackageInfo& packageInfo) const override;
 
     bool isSafeToKill(
-            const android::automotive::watchdog::internal::PackageInfo& packageInfo) const;
+            const android::automotive::watchdog::internal::PackageInfo& packageInfo) const override;
 
-    const IoOveruseAlertThresholdSet& systemWideAlertThresholds() { return mAlertThresholds; }
+    const IoOveruseAlertThresholdSet& systemWideAlertThresholds() override {
+        return mAlertThresholds;
+    }
 
-    const std::unordered_set<std::string>& vendorPackagePrefixes() {
+    const std::unordered_set<std::string>& vendorPackagePrefixes() override {
         return mVendorPackagePrefixes;
     }
 
     const std::unordered_map<std::string,
                              android::automotive::watchdog::internal::ApplicationCategoryType>&
-    packagesToAppCategories() {
+    packagesToAppCategories() override {
         return mPackagesToAppCategories;
     }
 
 private:
+    enum ConfigUpdateMode {
+        OVERWRITE = 0,
+        MERGE,
+        NO_UPDATE,
+    };
+    android::base::Result<void> updateFromXml(const char* filename);
+
+    void updateFromAidlConfig(
+            const android::automotive::watchdog::internal::ResourceOveruseConfiguration&
+                    resourceOveruseConfig);
+
     android::base::Result<void> update(
             const android::automotive::watchdog::internal::ResourceOveruseConfiguration&
                     resourceOveruseConfiguration,
@@ -199,6 +232,13 @@
                     ioOveruseConfiguration,
             int32_t updatableConfigsFilter, ComponentSpecificConfig* targetComponentConfig);
 
+    android::base::Result<void> updatePerCategoryThresholds(
+            const std::vector<android::automotive::watchdog::internal::PerStateIoOveruseThreshold>&
+                    thresholds);
+    android::base::Result<void> updateAlertThresholds(
+            const std::vector<android::automotive::watchdog::internal::IoOveruseAlertThreshold>&
+                    thresholds);
+
     std::optional<android::automotive::watchdog::internal::ResourceOveruseConfiguration> get(
             const ComponentSpecificConfig& componentSpecificConfig, const int32_t componentFilter);
 
@@ -212,6 +252,7 @@
     std::unordered_map<std::string,
                        android::automotive::watchdog::internal::ApplicationCategoryType>
             mPackagesToAppCategories;
+    ConfigUpdateMode mPackagesToAppCategoryMappingUpdateMode;
     // I/O overuse thresholds per category.
     std::unordered_map<android::automotive::watchdog::internal::ApplicationCategoryType,
                        android::automotive::watchdog::internal::PerStateIoOveruseThreshold>
@@ -221,12 +262,12 @@
     // System-wide disk I/O overuse alert thresholds.
     IoOveruseAlertThresholdSet mAlertThresholds;
 
-    android::base::Result<void> updatePerCategoryThresholds(
-            const std::vector<android::automotive::watchdog::internal::PerStateIoOveruseThreshold>&
-                    thresholds);
-    android::base::Result<void> updateAlertThresholds(
-            const std::vector<android::automotive::watchdog::internal::IoOveruseAlertThreshold>&
-                    thresholds);
+    // For unit tests.
+    using ParseXmlFileFunction = std::function<android::base::Result<
+            android::automotive::watchdog::internal::ResourceOveruseConfiguration>(const char*)>;
+    static ParseXmlFileFunction sParseXmlFile;
+
+    friend class internal::IoOveruseConfigsPeer;
 };
 
 }  // namespace watchdog
diff --git a/cpp/watchdog/server/src/IoOveruseMonitor.cpp b/cpp/watchdog/server/src/IoOveruseMonitor.cpp
index ddc606b..9790586 100644
--- a/cpp/watchdog/server/src/IoOveruseMonitor.cpp
+++ b/cpp/watchdog/server/src/IoOveruseMonitor.cpp
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2020, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -28,6 +28,7 @@
 #include <binder/IPCThreadState.h>
 #include <binder/Status.h>
 #include <cutils/multiuser.h>
+#include <log/log.h>
 
 #include <limits>
 
@@ -117,7 +118,7 @@
       mIoOveruseWarnPercentage(0),
       mLastUserPackageIoMonitorTime(0),
       mOveruseListenersByUid({}),
-      mBinderDeathRecipient(new BinderDeathRecipient(this)) {}
+      mBinderDeathRecipient(sp<BinderDeathRecipient>::make(this)) {}
 
 Result<void> IoOveruseMonitor::init() {
     std::unique_lock writeLock(mRwMutex);
@@ -134,17 +135,7 @@
     }
     mIoOveruseWarnPercentage = static_cast<double>(
             sysprop::ioOveruseWarnPercentage().value_or(kDefaultIoOveruseWarnPercentage));
-    /*
-     * TODO(b/185287136): Read the latest I/O overuse config.
-     *  The latest I/O overuse config is read in this order:
-     *  1. From /data partition as this contains the latest config and any updates received from OEM
-     *    and system applications.
-     *  2. From /system and /vendor partitions as this contains the default configs shipped with the
-     *    the image.
-     */
-
-    mIoOveruseConfigs = new IoOveruseConfigs();
-    // TODO(b/185287136): Read the vendor package prefixes from disk before the below call.
+    mIoOveruseConfigs = sp<IoOveruseConfigs>::make();
     mPackageInfoResolver = PackageInfoResolver::getInstance();
     mPackageInfoResolver->setPackageConfigurations(mIoOveruseConfigs->vendorPackagePrefixes(),
                                                    mIoOveruseConfigs->packagesToAppCategories());
@@ -187,10 +178,8 @@
     gmtime_r(&time, &curGmt);
     if (prevGmt.tm_yday != curGmt.tm_yday || prevGmt.tm_year != curGmt.tm_year) {
         /*
-         * Date changed so reset the daily I/O usage cache.
-         *
-         * TODO(b/185287136): Ping CarWatchdogService on date change so it can re-enable the daily
-         *  disabled packages. Also sync prev day's stats with CarWatchdogService.
+         * Date changed so reset the daily I/O usage cache. CarWatchdogService automatically handles
+         * date change on |CarWatchdogService.latestIoOveruseStats| call.
          */
         mUserPackageDailyIoUsageById.clear();
     }
diff --git a/cpp/watchdog/server/src/IoOveruseMonitor.h b/cpp/watchdog/server/src/IoOveruseMonitor.h
index e749eec..efac553 100644
--- a/cpp/watchdog/server/src/IoOveruseMonitor.h
+++ b/cpp/watchdog/server/src/IoOveruseMonitor.h
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2020, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/cpp/watchdog/server/src/WatchdogPerfService.cpp b/cpp/watchdog/server/src/WatchdogPerfService.cpp
index 030f318..151a5ef 100644
--- a/cpp/watchdog/server/src/WatchdogPerfService.cpp
+++ b/cpp/watchdog/server/src/WatchdogPerfService.cpp
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2020, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/cpp/watchdog/server/src/WatchdogPerfService.h b/cpp/watchdog/server/src/WatchdogPerfService.h
index 0551d35..6f1230a 100644
--- a/cpp/watchdog/server/src/WatchdogPerfService.h
+++ b/cpp/watchdog/server/src/WatchdogPerfService.h
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2020, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/cpp/watchdog/server/tests/IoOveruseConfigsTest.cpp b/cpp/watchdog/server/tests/IoOveruseConfigsTest.cpp
index 43d08d7..84f28bb 100644
--- a/cpp/watchdog/server/tests/IoOveruseConfigsTest.cpp
+++ b/cpp/watchdog/server/tests/IoOveruseConfigsTest.cpp
@@ -16,12 +16,15 @@
 
 #include "IoOveruseConfigs.h"
 #include "OveruseConfigurationTestUtils.h"
+#include "OveruseConfigurationXmlHelper.h"
 
 #include <android-base/strings.h>
 #include <gmock/gmock.h>
 
 #include <inttypes.h>
 
+#include <unordered_map>
+
 namespace android {
 namespace automotive {
 namespace watchdog {
@@ -36,6 +39,7 @@
 using ::android::automotive::watchdog::internal::ResourceOveruseConfiguration;
 using ::android::automotive::watchdog::internal::ResourceSpecificConfiguration;
 using ::android::automotive::watchdog::internal::UidType;
+using ::android::base::Error;
 using ::android::base::StringAppendF;
 using ::android::base::StringPrintf;
 using ::testing::IsEmpty;
@@ -100,7 +104,53 @@
     return matchers;
 }
 
-ResourceOveruseConfiguration sampleSystemConfig() {
+ResourceOveruseConfiguration sampleBuildSystemConfig() {
+    auto systemIoConfig = constructIoOveruseConfig(
+            /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::SYSTEM,
+                                                            toPerStateBytes(1200, 1100, 1500)),
+            /*packageSpecific=*/
+            {toPerStateIoOveruseThreshold("systemPackageA", SYSTEM_PACKAGE_A_THRESHOLDS)},
+            /*categorySpecific=*/{},
+            /*systemWide=*/ALERT_THRESHOLDS);
+    return constructResourceOveruseConfig(ComponentType::SYSTEM,
+                                          /*safeToKill=*/{"systemPackageA"},
+                                          /*vendorPrefixes=*/{},
+                                          /*packageMetadata*/
+                                          {toPackageMetadata("systemPackageA",
+                                                             ApplicationCategoryType::MEDIA)},
+                                          systemIoConfig);
+}
+
+ResourceOveruseConfiguration sampleBuildVendorConfig() {
+    auto vendorIoConfig = constructIoOveruseConfig(
+            /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::VENDOR,
+                                                            toPerStateBytes(1100, 150, 1900)),
+            /*packageSpecific=*/
+            {toPerStateIoOveruseThreshold("vendorPackageA", VENDOR_PACKAGE_A_THRESHOLDS)},
+            /*categorySpecific=*/
+            {toPerStateIoOveruseThreshold("MEDIA", MEDIA_THRESHOLDS)},
+            /*systemWide=*/{});
+    return constructResourceOveruseConfig(ComponentType::VENDOR,
+                                          /*safeToKill=*/{},
+                                          /*vendorPrefixes=*/{"vendorPackage"},
+                                          /*packageMetadata=*/
+                                          {toPackageMetadata("vendorPackageA",
+                                                             ApplicationCategoryType::MEDIA)},
+                                          vendorIoConfig);
+}
+
+ResourceOveruseConfiguration sampleBuildThirdPartyConfig() {
+    auto thirdPartyIoConfig = constructIoOveruseConfig(
+            /*componentLevel=*/
+            toPerStateIoOveruseThreshold(ComponentType::THIRD_PARTY,
+                                         toPerStateBytes(1300, 1150, 2900)),
+            /*packageSpecific=*/{}, /*categorySpecific=*/{}, /*systemWide=*/{});
+    return constructResourceOveruseConfig(ComponentType::THIRD_PARTY, /*safeToKill=*/{},
+                                          /*vendorPrefixes=*/{}, /*packageMetadata=*/{},
+                                          thirdPartyIoConfig);
+}
+
+ResourceOveruseConfiguration sampleUpdateSystemConfig() {
     auto systemIoConfig = constructIoOveruseConfig(
             /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::SYSTEM,
                                                             SYSTEM_COMPONENT_LEVEL_THRESHOLDS),
@@ -119,7 +169,7 @@
                                           systemIoConfig);
 }
 
-ResourceOveruseConfiguration sampleVendorConfig() {
+ResourceOveruseConfiguration sampleUpdateVendorConfig() {
     auto vendorIoConfig = constructIoOveruseConfig(
             /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::VENDOR,
                                                             VENDOR_COMPONENT_LEVEL_THRESHOLDS),
@@ -141,7 +191,7 @@
                                           vendorIoConfig);
 }
 
-ResourceOveruseConfiguration sampleThirdPartyConfig() {
+ResourceOveruseConfiguration sampleUpdateThirdPartyConfig() {
     auto thirdPartyIoConfig = constructIoOveruseConfig(
             /*componentLevel=*/
             toPerStateIoOveruseThreshold(ComponentType::THIRD_PARTY,
@@ -154,17 +204,198 @@
 
 sp<IoOveruseConfigs> sampleIoOveruseConfigs() {
     sp<IoOveruseConfigs> ioOveruseConfigs = new IoOveruseConfigs();
-    EXPECT_RESULT_OK(ioOveruseConfigs->update(
-            {sampleSystemConfig(), sampleVendorConfig(), sampleThirdPartyConfig()}));
+    EXPECT_RESULT_OK(
+            ioOveruseConfigs->update({sampleUpdateSystemConfig(), sampleUpdateVendorConfig(),
+                                      sampleUpdateThirdPartyConfig()}));
     return ioOveruseConfigs;
 }
 
 }  // namespace
 
-TEST(IoOveruseConfigsTest, TestUpdateWithValidConfigs) {
-    auto systemResourceConfig = sampleSystemConfig();
-    auto vendorResourceConfig = sampleVendorConfig();
-    auto thirdPartyResourceConfig = sampleThirdPartyConfig();
+namespace internal {
+
+class IoOveruseConfigsPeer : public android::RefBase {
+public:
+    IoOveruseConfigsPeer() {
+        IoOveruseConfigs::sParseXmlFile =
+                [&](const char* filepath) -> android::base::Result<ResourceOveruseConfiguration> {
+            if (const auto it = configsByFilepaths.find(filepath); it != configsByFilepaths.end()) {
+                return it->second;
+            }
+            return Error() << "No configs available for the given filepath '" << filepath << "'";
+        };
+    }
+    ~IoOveruseConfigsPeer() {
+        IoOveruseConfigs::sParseXmlFile = &OveruseConfigurationXmlHelper::parseXmlFile;
+    }
+    std::unordered_map<std::string, ResourceOveruseConfiguration> configsByFilepaths;
+};
+
+}  // namespace internal
+
+class IoOveruseConfigsTest : public ::testing::Test {
+public:
+    virtual void SetUp() { mPeer = sp<internal::IoOveruseConfigsPeer>::make(); }
+    virtual void TearDown() { mPeer.clear(); }
+
+    sp<internal::IoOveruseConfigsPeer> mPeer;
+};
+
+TEST_F(IoOveruseConfigsTest, TestConstructWithBuildConfigs) {
+    auto buildSystemResourceConfig = sampleBuildSystemConfig();
+    auto buildVendorResourceConfig = sampleBuildVendorConfig();
+    const auto buildThirdPartyResourceConfig = sampleBuildThirdPartyConfig();
+
+    mPeer->configsByFilepaths = {{kBuildSystemConfigXmlPath, buildSystemResourceConfig},
+                                 {kBuildVendorConfigXmlPath, buildVendorResourceConfig},
+                                 {kBuildThirdPartyConfigXmlPath, buildThirdPartyResourceConfig}};
+
+    IoOveruseConfigs ioOveruseConfigs;
+
+    /* Package to app category mapping should be merged from both vendor and system configs. */
+    buildVendorResourceConfig.packageMetadata
+            .insert(buildVendorResourceConfig.packageMetadata.end(),
+                    buildSystemResourceConfig.packageMetadata.begin(),
+                    buildSystemResourceConfig.packageMetadata.end());
+    buildSystemResourceConfig.packageMetadata = buildVendorResourceConfig.packageMetadata;
+    std::vector<ResourceOveruseConfiguration> expected = {buildSystemResourceConfig,
+                                                          buildVendorResourceConfig,
+                                                          buildThirdPartyResourceConfig};
+
+    std::vector<ResourceOveruseConfiguration> actual;
+    ioOveruseConfigs.get(&actual);
+
+    EXPECT_THAT(actual, UnorderedElementsAreArray(ResourceOveruseConfigurationsMatchers(expected)))
+            << "Expected: " << toString(expected) << "Actual:" << toString(actual);
+}
+
+TEST_F(IoOveruseConfigsTest, TestConstructWithLatestConfigs) {
+    const auto latestSystemResourceConfig = sampleUpdateSystemConfig();
+    auto latestVendorResourceConfig = sampleUpdateVendorConfig();
+    const auto latestThirdPartyResourceConfig = sampleUpdateThirdPartyConfig();
+
+    mPeer->configsByFilepaths = {{kBuildSystemConfigXmlPath, sampleBuildSystemConfig()},
+                                 {kBuildVendorConfigXmlPath, sampleBuildVendorConfig()},
+                                 {kBuildThirdPartyConfigXmlPath, sampleBuildThirdPartyConfig()},
+                                 {kLatestSystemConfigXmlPath, latestSystemResourceConfig},
+                                 {kLatestVendorConfigXmlPath, latestVendorResourceConfig},
+                                 {kLatestThirdPartyConfigXmlPath, latestThirdPartyResourceConfig}};
+
+    IoOveruseConfigs ioOveruseConfigs;
+
+    latestVendorResourceConfig.vendorPackagePrefixes.push_back("vendorPkgB");
+    std::vector<ResourceOveruseConfiguration> expected = {latestSystemResourceConfig,
+                                                          latestVendorResourceConfig,
+                                                          latestThirdPartyResourceConfig};
+
+    std::vector<ResourceOveruseConfiguration> actual;
+    ioOveruseConfigs.get(&actual);
+
+    EXPECT_THAT(actual, UnorderedElementsAreArray(ResourceOveruseConfigurationsMatchers(expected)))
+            << "Expected: " << toString(expected) << "Actual:" << toString(actual);
+}
+
+TEST_F(IoOveruseConfigsTest, TestConstructWithOnlyBuildSystemConfig) {
+    const auto buildSystemResourceConfig = sampleBuildSystemConfig();
+
+    mPeer->configsByFilepaths = {{kBuildSystemConfigXmlPath, buildSystemResourceConfig}};
+
+    IoOveruseConfigs ioOveruseConfigs;
+
+    /*
+     * Vendor/Third-party component-level thresholds should be derived from system
+     * component-level thresholds when build configs for Vendor/Third-party components are not
+     * available.
+     */
+    const auto& defaultComponentLevelThresholds =
+            buildSystemResourceConfig.resourceSpecificConfigurations[0]
+                    .get<ResourceSpecificConfiguration::ioOveruseConfiguration>()
+                    .componentLevelThresholds.perStateWriteBytes;
+    const auto vendorResourceConfig = constructResourceOveruseConfig(
+            ComponentType::VENDOR, /*safeToKill=*/{}, /*vendorPrefixes=*/{},
+            /*packageMetadata=*/buildSystemResourceConfig.packageMetadata,
+            constructIoOveruseConfig(
+                    /*componentLevel=*/
+                    toPerStateIoOveruseThreshold(ComponentType::VENDOR,
+                                                 defaultComponentLevelThresholds),
+                    /*packageSpecific=*/{}, /*categorySpecific=*/{}, /*systemWide=*/{}));
+    const auto thirdPartyResourceConfig =
+            constructResourceOveruseConfig(ComponentType::THIRD_PARTY, /*safeToKill=*/{},
+                                           /*vendorPrefixes=*/{},
+                                           /*packageMetadata=*/{},
+                                           constructIoOveruseConfig(
+                                                   /*componentLevel=*/toPerStateIoOveruseThreshold(
+                                                           ComponentType::THIRD_PARTY,
+                                                           defaultComponentLevelThresholds),
+                                                   /*packageSpecific=*/{}, /*categorySpecific=*/{},
+                                                   /*systemWide=*/{}));
+
+    std::vector<ResourceOveruseConfiguration> expected = {buildSystemResourceConfig,
+                                                          vendorResourceConfig,
+                                                          thirdPartyResourceConfig};
+
+    std::vector<ResourceOveruseConfiguration> actual;
+    ioOveruseConfigs.get(&actual);
+
+    EXPECT_THAT(actual, UnorderedElementsAreArray(ResourceOveruseConfigurationsMatchers(expected)))
+            << "Expected: " << toString(expected) << "Actual:" << toString(actual);
+}
+
+TEST_F(IoOveruseConfigsTest, TestConstructWithBuildSystemConfigLatestVendorConfig) {
+    auto buildSystemResourceConfig = sampleBuildSystemConfig();
+    auto latestVendorResourceConfig = sampleUpdateVendorConfig();
+    const auto buildThirdPartyResourceConfig = sampleBuildThirdPartyConfig();
+
+    mPeer->configsByFilepaths = {{kBuildSystemConfigXmlPath, buildSystemResourceConfig},
+                                 {kBuildVendorConfigXmlPath, sampleBuildVendorConfig()},
+                                 {kBuildThirdPartyConfigXmlPath, buildThirdPartyResourceConfig},
+                                 {kLatestVendorConfigXmlPath, latestVendorResourceConfig}};
+
+    IoOveruseConfigs ioOveruseConfigs;
+
+    // Package to app category mapping from latest vendor configuration should be given priority.
+    buildSystemResourceConfig.packageMetadata = latestVendorResourceConfig.packageMetadata;
+    latestVendorResourceConfig.vendorPackagePrefixes.push_back("vendorPkgB");
+    std::vector<ResourceOveruseConfiguration> expected = {buildSystemResourceConfig,
+                                                          latestVendorResourceConfig,
+                                                          buildThirdPartyResourceConfig};
+
+    std::vector<ResourceOveruseConfiguration> actual;
+    ioOveruseConfigs.get(&actual);
+
+    EXPECT_THAT(actual, UnorderedElementsAreArray(ResourceOveruseConfigurationsMatchers(expected)))
+            << "Expected: " << toString(expected) << "Actual:" << toString(actual);
+}
+
+TEST_F(IoOveruseConfigsTest, TestConstructWithLatestSystemConfigBuildVendorConfig) {
+    const auto latestSystemResourceConfig = sampleUpdateSystemConfig();
+    auto buildVendorResourceConfig = sampleBuildVendorConfig();
+    const auto buildThirdPartyResourceConfig = sampleBuildThirdPartyConfig();
+
+    mPeer->configsByFilepaths = {{kBuildSystemConfigXmlPath, sampleBuildSystemConfig()},
+                                 {kBuildVendorConfigXmlPath, sampleBuildVendorConfig()},
+                                 {kBuildThirdPartyConfigXmlPath, buildThirdPartyResourceConfig},
+                                 {kLatestSystemConfigXmlPath, latestSystemResourceConfig}};
+
+    IoOveruseConfigs ioOveruseConfigs;
+
+    // Package to app category mapping from latest system configuration should be given priority.
+    buildVendorResourceConfig.packageMetadata = latestSystemResourceConfig.packageMetadata;
+    std::vector<ResourceOveruseConfiguration> expected = {latestSystemResourceConfig,
+                                                          buildVendorResourceConfig,
+                                                          buildThirdPartyResourceConfig};
+
+    std::vector<ResourceOveruseConfiguration> actual;
+    ioOveruseConfigs.get(&actual);
+
+    EXPECT_THAT(actual, UnorderedElementsAreArray(ResourceOveruseConfigurationsMatchers(expected)))
+            << "Expected: " << toString(expected) << "Actual:" << toString(actual);
+}
+
+TEST_F(IoOveruseConfigsTest, TestUpdateWithValidConfigs) {
+    auto systemResourceConfig = sampleUpdateSystemConfig();
+    auto vendorResourceConfig = sampleUpdateVendorConfig();
+    auto thirdPartyResourceConfig = sampleUpdateThirdPartyConfig();
 
     IoOveruseConfigs ioOveruseConfigs;
     ASSERT_RESULT_OK(ioOveruseConfigs.update(
@@ -248,7 +479,7 @@
             << "Expected: " << toString(expected) << "Actual:" << toString(actual);
 }
 
-TEST(IoOveruseConfigsTest, TestDefaultConfigWithoutUpdate) {
+TEST_F(IoOveruseConfigsTest, TestDefaultConfigWithoutUpdate) {
     PerStateBytes defaultPerStateBytes = defaultThreshold().perStateWriteBytes;
     IoOveruseConfigs ioOveruseConfigs;
 
@@ -281,7 +512,7 @@
     EXPECT_THAT(actual, IsEmpty());
 }
 
-TEST(IoOveruseConfigsTest, TestFailsUpdateOnInvalidComponentName) {
+TEST_F(IoOveruseConfigsTest, TestFailsUpdateOnInvalidComponentName) {
     IoOveruseConfiguration randomIoConfig;
     randomIoConfig.componentLevelThresholds =
             toPerStateIoOveruseThreshold("random name", 200, 100, 500);
@@ -308,7 +539,32 @@
     EXPECT_THAT(actual, IsEmpty());
 }
 
-TEST(IoOveruseConfigsTest, TestFailsUpdateOnInvalidComponentLevelThresholds) {
+TEST_F(IoOveruseConfigsTest, TestFailsUpdateOnDuplicatePackageToAppCategoryMappings) {
+    IoOveruseConfiguration ioConfig;
+    ioConfig.componentLevelThresholds =
+            toPerStateIoOveruseThreshold(ComponentType::VENDOR, VENDOR_COMPONENT_LEVEL_THRESHOLDS);
+
+    IoOveruseConfigs ioOveruseConfigs;
+    EXPECT_FALSE(
+            ioOveruseConfigs
+                    .update({constructResourceOveruseConfig(
+                            ComponentType::VENDOR,
+                            /*safeToKill=*/{},
+                            /*vendorPrefixes=*/{"vendorPackage"},
+                            /*packageMetadata=*/
+                            {toPackageMetadata("vendorPackageA", ApplicationCategoryType::MEDIA),
+                             toPackageMetadata("vendorPackageA", ApplicationCategoryType::MAPS)},
+                            ioConfig)})
+                    .ok())
+            << "Should error on duplicate package to app category mapping";
+
+    std::vector<ResourceOveruseConfiguration> actual;
+    ioOveruseConfigs.get(&actual);
+
+    EXPECT_THAT(actual, IsEmpty());
+}
+
+TEST_F(IoOveruseConfigsTest, TestFailsUpdateOnInvalidComponentLevelThresholds) {
     IoOveruseConfiguration ioConfig;
     ioConfig.componentLevelThresholds =
             toPerStateIoOveruseThreshold(ComponentType::THIRD_PARTY, 0, 0, 0);
@@ -326,7 +582,7 @@
     EXPECT_THAT(actual, IsEmpty());
 }
 
-TEST(IoOveruseConfigsTest, TestFailsUpdateOnInvalidSystemWideAlertThresholds) {
+TEST_F(IoOveruseConfigsTest, TestFailsUpdateOnInvalidSystemWideAlertThresholds) {
     IoOveruseConfiguration ioConfig;
     ioConfig.componentLevelThresholds =
             toPerStateIoOveruseThreshold(ComponentType::SYSTEM, 100, 200, 300);
@@ -345,9 +601,11 @@
     EXPECT_THAT(actual, IsEmpty());
 }
 
-TEST(IoOveruseConfigsTest, TestFailsUpdateOnDuplicateConfigsForSameComponent) {
+TEST_F(IoOveruseConfigsTest, TestFailsUpdateOnDuplicateConfigsForSameComponent) {
     IoOveruseConfigs ioOveruseConfigs;
-    EXPECT_FALSE(ioOveruseConfigs.update({sampleThirdPartyConfig(), sampleThirdPartyConfig()}).ok())
+    EXPECT_FALSE(ioOveruseConfigs
+                         .update({sampleUpdateThirdPartyConfig(), sampleUpdateThirdPartyConfig()})
+                         .ok())
             << "Should error on duplicate configs for the same component";
 
     std::vector<ResourceOveruseConfiguration> actual;
@@ -356,7 +614,7 @@
     EXPECT_THAT(actual, IsEmpty());
 }
 
-TEST(IoOveruseConfigsTest, TestFailsUpdateOnNoIoOveruseConfiguration) {
+TEST_F(IoOveruseConfigsTest, TestFailsUpdateOnNoIoOveruseConfiguration) {
     ResourceOveruseConfiguration resConfig;
     resConfig.componentType = ComponentType::THIRD_PARTY;
 
@@ -370,7 +628,7 @@
     EXPECT_THAT(actual, IsEmpty());
 }
 
-TEST(IoOveruseConfigsTest, TestFailsUpdateOnMultipleIoOveruseConfigurations) {
+TEST_F(IoOveruseConfigsTest, TestFailsUpdateOnMultipleIoOveruseConfigurations) {
     IoOveruseConfiguration ioConfig;
     ioConfig.componentLevelThresholds =
             toPerStateIoOveruseThreshold(ComponentType::THIRD_PARTY, 100, 200, 300);
@@ -392,7 +650,7 @@
     EXPECT_THAT(actual, IsEmpty());
 }
 
-TEST(IoOveruseConfigsTest, TestIgnoresNonUpdatableConfigsBySystemComponent) {
+TEST_F(IoOveruseConfigsTest, TestIgnoresNonUpdatableConfigsBySystemComponent) {
     auto systemIoConfig = constructIoOveruseConfig(
             /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::SYSTEM, 200, 100, 500),
             /*packageSpecific=*/
@@ -427,7 +685,7 @@
             << "Expected: " << toString(expected) << "Actual:" << toString(actual);
 }
 
-TEST(IoOveruseConfigsTest, TestIgnoresNonUpdatableConfigsByVendorComponent) {
+TEST_F(IoOveruseConfigsTest, TestIgnoresNonUpdatableConfigsByVendorComponent) {
     auto vendorIoConfig = constructIoOveruseConfig(
             /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::VENDOR, 100, 50, 900),
             /*packageSpecific=*/
@@ -466,7 +724,7 @@
             << "Expected: " << toString(expected) << "Actual:" << toString(actual);
 }
 
-TEST(IoOveruseConfigsTest, TestIgnoresNonUpdatableConfigsByThirdPartyComponent) {
+TEST_F(IoOveruseConfigsTest, TestIgnoresNonUpdatableConfigsByThirdPartyComponent) {
     auto thirdPartyIoConfig = constructIoOveruseConfig(
             /*componentLevel=*/
             toPerStateIoOveruseThreshold(ComponentType::THIRD_PARTY, 300, 150, 1900),
@@ -505,7 +763,7 @@
             << "Expected: " << toString(expected) << "Actual:" << toString(actual);
 }
 
-TEST(IoOveruseConfigsTest, TestFetchThresholdForSystemPackages) {
+TEST_F(IoOveruseConfigsTest, TestFetchThresholdForSystemPackages) {
     const auto ioOveruseConfigs = sampleIoOveruseConfigs();
 
     auto actual = ioOveruseConfigs->fetchThreshold(
@@ -533,7 +791,7 @@
     EXPECT_THAT(actual, MEDIA_THRESHOLDS);
 }
 
-TEST(IoOveruseConfigsTest, TestFetchThresholdForVendorPackages) {
+TEST_F(IoOveruseConfigsTest, TestFetchThresholdForVendorPackages) {
     const auto ioOveruseConfigs = sampleIoOveruseConfigs();
 
     auto actual = ioOveruseConfigs->fetchThreshold(
@@ -554,7 +812,7 @@
     EXPECT_THAT(actual, MAPS_THRESHOLDS);
 }
 
-TEST(IoOveruseConfigsTest, TestFetchThresholdForThirdPartyPackages) {
+TEST_F(IoOveruseConfigsTest, TestFetchThresholdForThirdPartyPackages) {
     const auto ioOveruseConfigs = sampleIoOveruseConfigs();
 
     auto actual = ioOveruseConfigs->fetchThreshold(
@@ -575,7 +833,7 @@
     EXPECT_THAT(actual, MEDIA_THRESHOLDS);
 }
 
-TEST(IoOveruseConfigsTest, TestIsSafeToKillSystemPackages) {
+TEST_F(IoOveruseConfigsTest, TestIsSafeToKillSystemPackages) {
     const auto ioOveruseConfigs = sampleIoOveruseConfigs();
     EXPECT_FALSE(ioOveruseConfigs->isSafeToKill(
             constructPackageInfo("systemPackageGeneric", ComponentType::SYSTEM)));
@@ -584,7 +842,7 @@
             constructPackageInfo("systemPackageA", ComponentType::SYSTEM)));
 }
 
-TEST(IoOveruseConfigsTest, TestIsSafeToKillVendorPackages) {
+TEST_F(IoOveruseConfigsTest, TestIsSafeToKillVendorPackages) {
     const auto ioOveruseConfigs = sampleIoOveruseConfigs();
     EXPECT_FALSE(ioOveruseConfigs->isSafeToKill(
             constructPackageInfo("vendorPackageGeneric", ComponentType::VENDOR)));
@@ -593,7 +851,7 @@
             constructPackageInfo("vendorPackageA", ComponentType::VENDOR)));
 }
 
-TEST(IoOveruseConfigsTest, TestIsSafeToKillThirdPartyPackages) {
+TEST_F(IoOveruseConfigsTest, TestIsSafeToKillThirdPartyPackages) {
     const auto ioOveruseConfigs = sampleIoOveruseConfigs();
     EXPECT_TRUE(ioOveruseConfigs->isSafeToKill(
             constructPackageInfo("vendorPackageGenericImpostor", ComponentType::THIRD_PARTY)));
@@ -603,7 +861,7 @@
                                  ApplicationCategoryType::MAPS)));
 }
 
-TEST(IoOveruseConfigsTest, TestIsSafeToKillNativePackages) {
+TEST_F(IoOveruseConfigsTest, TestIsSafeToKillNativePackages) {
     const auto ioOveruseConfigs = sampleIoOveruseConfigs();
 
     PackageInfo packageInfo;
@@ -618,23 +876,23 @@
     EXPECT_FALSE(ioOveruseConfigs->isSafeToKill(packageInfo));
 }
 
-TEST(IoOveruseConfigsTest, TestSystemWideAlertThresholds) {
+TEST_F(IoOveruseConfigsTest, TestSystemWideAlertThresholds) {
     const auto ioOveruseConfigs = sampleIoOveruseConfigs();
 
     EXPECT_THAT(ioOveruseConfigs->systemWideAlertThresholds(),
                 UnorderedElementsAreArray(ALERT_THRESHOLDS));
 }
 
-TEST(IoOveruseConfigsTest, TestVendorPackagePrefixes) {
+TEST_F(IoOveruseConfigsTest, TestVendorPackagePrefixes) {
     const auto ioOveruseConfigs = sampleIoOveruseConfigs();
 
     EXPECT_THAT(ioOveruseConfigs->vendorPackagePrefixes(),
                 UnorderedElementsAre("vendorPackage", "vendorPkgB"));
 }
 
-TEST(IoOveruseConfigsTest, TestPackagesToAppCategoriesWithSystemConfig) {
+TEST_F(IoOveruseConfigsTest, TestPackagesToAppCategoriesWithSystemConfig) {
     IoOveruseConfigs ioOveruseConfigs;
-    const auto resourceOveruseConfig = sampleSystemConfig();
+    const auto resourceOveruseConfig = sampleUpdateSystemConfig();
 
     ASSERT_RESULT_OK(ioOveruseConfigs.update({resourceOveruseConfig}));
 
@@ -643,9 +901,9 @@
                         toPackageToAppCategoryMappings(resourceOveruseConfig.packageMetadata)));
 }
 
-TEST(IoOveruseConfigsTest, TestPackagesToAppCategoriesWithVendorConfig) {
+TEST_F(IoOveruseConfigsTest, TestPackagesToAppCategoriesWithVendorConfig) {
     IoOveruseConfigs ioOveruseConfigs;
-    const auto resourceOveruseConfig = sampleVendorConfig();
+    const auto resourceOveruseConfig = sampleUpdateVendorConfig();
 
     ASSERT_RESULT_OK(ioOveruseConfigs.update({resourceOveruseConfig}));
 
diff --git a/cpp/watchdog/server/tests/OveruseConfigurationTestUtils.cpp b/cpp/watchdog/server/tests/OveruseConfigurationTestUtils.cpp
index ec5908a..1bf270d 100644
--- a/cpp/watchdog/server/tests/OveruseConfigurationTestUtils.cpp
+++ b/cpp/watchdog/server/tests/OveruseConfigurationTestUtils.cpp
@@ -67,6 +67,11 @@
     }
 }
 
+MATCHER_P(IsPackageMetadata, expected, "") {
+    return arg.packageName == expected.packageName &&
+            arg.appCategoryType == expected.appCategoryType;
+}
+
 }  // namespace
 
 ResourceOveruseConfiguration constructResourceOveruseConfig(
@@ -151,9 +156,15 @@
 
 Matcher<const ResourceOveruseConfiguration> ResourceOveruseConfigurationMatcher(
         const ResourceOveruseConfiguration& config) {
-    std::vector<Matcher<const ResourceSpecificConfiguration>> matchers;
+    std::vector<Matcher<const ResourceSpecificConfiguration>> resourceSpecificConfigMatchers;
     for (const auto& resourceSpecificConfig : config.resourceSpecificConfigurations) {
-        matchers.push_back(IsResourceSpecificConfiguration(resourceSpecificConfig));
+        resourceSpecificConfigMatchers.push_back(
+                IsResourceSpecificConfiguration(resourceSpecificConfig));
+    }
+
+    std::vector<Matcher<const PackageMetadata>> metadataMatchers;
+    for (const auto& metadata : config.packageMetadata) {
+        metadataMatchers.push_back(IsPackageMetadata(metadata));
     }
 
     return AllOf(Field(&ResourceOveruseConfiguration::componentType, config.componentType),
@@ -161,8 +172,10 @@
                        UnorderedElementsAreArray(config.safeToKillPackages)),
                  Field(&ResourceOveruseConfiguration::vendorPackagePrefixes,
                        UnorderedElementsAreArray(config.vendorPackagePrefixes)),
+                 Field(&ResourceOveruseConfiguration::packageMetadata,
+                       UnorderedElementsAreArray(metadataMatchers)),
                  Field(&ResourceOveruseConfiguration::resourceSpecificConfigurations,
-                       UnorderedElementsAreArray(matchers)));
+                       UnorderedElementsAreArray(resourceSpecificConfigMatchers)));
 }
 
 }  // namespace watchdog
diff --git a/cpp/watchdog/server/tests/WatchdogInternalHandlerTest.cpp b/cpp/watchdog/server/tests/WatchdogInternalHandlerTest.cpp
index 40d6389..47d82b7 100644
--- a/cpp/watchdog/server/tests/WatchdogInternalHandlerTest.cpp
+++ b/cpp/watchdog/server/tests/WatchdogInternalHandlerTest.cpp
@@ -30,7 +30,6 @@
 #include <binder/IPCThreadState.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
-#include <log/log.h>
 #include <private/android_filesystem_config.h>
 #include <utils/RefBase.h>