Merge changes I94e08d61,I431fe6b7 into sc-dev

* changes:
  Read the on-device XML configurations on initialization.
  Convert per state thresholds read from XML configs.
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/OveruseConfigurationXmlHelper.cpp b/cpp/watchdog/server/src/OveruseConfigurationXmlHelper.cpp
index f76bcc5..f3d0f04 100644
--- a/cpp/watchdog/server/src/OveruseConfigurationXmlHelper.cpp
+++ b/cpp/watchdog/server/src/OveruseConfigurationXmlHelper.cpp
@@ -233,22 +233,23 @@
         if (seenStates.find(state) != seenStates.end()) {
             return Error() << "Duplicate threshold specified for state '" << state << "'";
         }
-        int64_t bytes = 0;
+        int64_t megaBytes = 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)) {
+        } else if (const auto megaBytesStr = Trim(text);
+                   !ParseInt(megaBytesStr.c_str(), &megaBytes)) {
             return Error() << "Failed to parse threshold for the state '" << state
-                           << "': Received threshold value '" << bytesStr << "'";
+                           << "': Received threshold value '" << megaBytesStr << "'";
         }
         if (!strcmp(state, kStateIdForegroundMode)) {
             seenStates.insert(kStateIdForegroundMode);
-            perStateBytes.foregroundBytes = bytes;
+            perStateBytes.foregroundBytes = megaBytes * kOneMegaByte;
         } else if (!strcmp(state, kStateIdBackgroundMode)) {
             seenStates.insert(kStateIdBackgroundMode);
-            perStateBytes.backgroundBytes = bytes;
+            perStateBytes.backgroundBytes = megaBytes * kOneMegaByte;
         } else if (!strcmp(state, kStateIdGarageMode)) {
             seenStates.insert(kStateIdGarageMode);
-            perStateBytes.garageModeBytes = bytes;
+            perStateBytes.garageModeBytes = megaBytes * kOneMegaByte;
         } else {
             return Error() << "Invalid state '" << state << "' in per-state bytes";
         }
diff --git a/cpp/watchdog/server/src/OveruseConfigurationXmlHelper.h b/cpp/watchdog/server/src/OveruseConfigurationXmlHelper.h
index 9f501c4..382c4f5 100644
--- a/cpp/watchdog/server/src/OveruseConfigurationXmlHelper.h
+++ b/cpp/watchdog/server/src/OveruseConfigurationXmlHelper.h
@@ -25,6 +25,8 @@
 namespace automotive {
 namespace watchdog {
 
+constexpr int64_t kOneMegaByte = 1024 * 1024;
+
 class OveruseConfigurationXmlHelper : public android::RefBase {
 public:
     static android::base::Result<
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/OveruseConfigurationXmlHelperTest.cpp b/cpp/watchdog/server/tests/OveruseConfigurationXmlHelperTest.cpp
index 2595c2b..88006d7 100644
--- a/cpp/watchdog/server/tests/OveruseConfigurationXmlHelperTest.cpp
+++ b/cpp/watchdog/server/tests/OveruseConfigurationXmlHelperTest.cpp
@@ -72,10 +72,14 @@
 
 TEST(OveruseConfigurationXmlHelperTest, TestValidSystemConfiguration) {
     auto ioConfig = constructIoOveruseConfig(
-            /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::SYSTEM, 300, 150, 500),
+            /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::SYSTEM,
+                                                            300 * kOneMegaByte, 150 * kOneMegaByte,
+                                                            500 * kOneMegaByte),
             /*packageSpecific=*/
-            {toPerStateIoOveruseThreshold("system.package.C", 400, 100, 200),
-             toPerStateIoOveruseThreshold("system.package.D", 1024, 500, 2048)},
+            {toPerStateIoOveruseThreshold("system.package.C", 400 * kOneMegaByte,
+                                          100 * kOneMegaByte, 200 * kOneMegaByte),
+             toPerStateIoOveruseThreshold("system.package.D", 1024 * kOneMegaByte,
+                                          500 * kOneMegaByte, 2048 * kOneMegaByte)},
             /*categorySpecific=*/{},
             /*systemWide=*/{toIoOveruseAlertThreshold(10, 200), toIoOveruseAlertThreshold(5, 50)});
     ResourceOveruseConfiguration expected =
@@ -97,13 +101,19 @@
 
 TEST(OveruseConfigurationXmlHelperTest, TestValidVendorConfiguration) {
     auto ioConfig = constructIoOveruseConfig(
-            /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::VENDOR, 1024, 512, 3072),
+            /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::VENDOR,
+                                                            1024 * kOneMegaByte, 512 * kOneMegaByte,
+                                                            3072 * kOneMegaByte),
             /*packageSpecific=*/
-            {toPerStateIoOveruseThreshold("com.vendor.package.C", 400, 100, 200),
-             toPerStateIoOveruseThreshold("com.vendor.package.D", 1024, 500, 2048)},
+            {toPerStateIoOveruseThreshold("com.vendor.package.C", 400 * kOneMegaByte,
+                                          100 * kOneMegaByte, 200 * kOneMegaByte),
+             toPerStateIoOveruseThreshold("com.vendor.package.D", 1024 * kOneMegaByte,
+                                          500 * kOneMegaByte, 2048 * kOneMegaByte)},
             /*categorySpecific=*/
-            {toPerStateIoOveruseThreshold("MAPS", 800, 900, 2048),
-             toPerStateIoOveruseThreshold("MEDIA", 600, 700, 1024)},
+            {toPerStateIoOveruseThreshold("MAPS", 800 * kOneMegaByte, 900 * kOneMegaByte,
+                                          2048 * kOneMegaByte),
+             toPerStateIoOveruseThreshold("MEDIA", 600 * kOneMegaByte, 700 * kOneMegaByte,
+                                          1024 * kOneMegaByte)},
             /*systemWide=*/{});
     ResourceOveruseConfiguration expected =
             constructResourceOveruseConfig(ComponentType::VENDOR,
@@ -129,8 +139,9 @@
 
 TEST(OveruseConfigurationXmlHelperTest, TestValidThirdPartyConfiguration) {
     auto ioConfig = constructIoOveruseConfig(
-            /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::THIRD_PARTY, 300, 150,
-                                                            500),
+            /*componentLevel=*/toPerStateIoOveruseThreshold(ComponentType::THIRD_PARTY,
+                                                            300 * kOneMegaByte, 150 * kOneMegaByte,
+                                                            500 * kOneMegaByte),
             /*packageSpecific=*/{},
             /*categorySpecific=*/{},
             /*systemWide=*/{});
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>
 
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
index b3bacb6..f12a47c 100644
--- a/cpp/watchdog/server/tests/data/valid_overuse_third_party_configuration.xml
+++ b/cpp/watchdog/server/tests/data/valid_overuse_third_party_configuration.xml
@@ -24,4 +24,4 @@
       <state id="garage_mode"> 500 </state>
     </componentLevelThresholds>
   </ioOveruseConfiguration>
-</resourceOveruseConfiguration>
\ No newline at end of file
+</resourceOveruseConfiguration>