1 /*
2  * Copyright (c) 2020, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef CPP_WATCHDOG_SERVER_SRC_IOOVERUSECONFIGS_H_
18 #define CPP_WATCHDOG_SERVER_SRC_IOOVERUSECONFIGS_H_
19 
20 #include <aidl/android/automotive/watchdog/PerStateBytes.h>
21 #include <aidl/android/automotive/watchdog/internal/ApplicationCategoryType.h>
22 #include <aidl/android/automotive/watchdog/internal/ComponentType.h>
23 #include <aidl/android/automotive/watchdog/internal/IoOveruseAlertThreshold.h>
24 #include <aidl/android/automotive/watchdog/internal/PackageInfo.h>
25 #include <aidl/android/automotive/watchdog/internal/PerStateIoOveruseThreshold.h>
26 #include <aidl/android/automotive/watchdog/internal/ResourceOveruseConfiguration.h>
27 #include <android-base/result.h>
28 #include <android-base/stringprintf.h>
29 #include <utils/RefBase.h>
30 
31 #include <optional>
32 #include <string>
33 #include <string_view>
34 #include <unordered_map>
35 #include <unordered_set>
36 #include <vector>
37 
38 namespace android {
39 namespace automotive {
40 namespace watchdog {
41 constexpr const char kBuildSystemConfigXmlPath[] =
42         "/system/etc/automotive/watchdog/system_resource_overuse_configuration.xml";
43 constexpr const char kBuildThirdPartyConfigXmlPath[] =
44         "/system/etc/automotive/watchdog/third_party_resource_overuse_configuration.xml";
45 constexpr const char kBuildVendorConfigXmlPath[] =
46         "/vendor/etc/automotive/watchdog/resource_overuse_configuration.xml";
47 constexpr const char kLatestSystemConfigXmlPath[] =
48         "/data/system/car/watchdog/system_resource_overuse_configuration.xml";
49 constexpr const char kLatestVendorConfigXmlPath[] =
50         "/data/system/car/watchdog/vendor_resource_overuse_configuration.xml";
51 constexpr const char kLatestThirdPartyConfigXmlPath[] =
52         "/data/system/car/watchdog/third_party_resource_overuse_configuration.xml";
53 constexpr const char kDefaultThresholdName[] = "default";
54 
55 inline const aidl::android::automotive::watchdog::internal::PerStateIoOveruseThreshold
defaultThreshold()56 defaultThreshold() {
57     aidl::android::automotive::watchdog::internal::PerStateIoOveruseThreshold threshold;
58     threshold.name = kDefaultThresholdName;
59     threshold.perStateWriteBytes.foregroundBytes = std::numeric_limits<int64_t>::max();
60     threshold.perStateWriteBytes.backgroundBytes = std::numeric_limits<int64_t>::max();
61     threshold.perStateWriteBytes.garageModeBytes = std::numeric_limits<int64_t>::max();
62     return threshold;
63 }
64 
65 // Forward declaration for testing use only.
66 namespace internal {
67 
68 class IoOveruseConfigsPeer;
69 
70 }  // namespace internal
71 
72 /**
73  * Defines the methods that the I/O overuse configs module should implement.
74  */
75 class IoOveruseConfigsInterface : virtual public android::RefBase {
76 public:
77     // Overwrites the existing configurations.
78     virtual android::base::Result<void> update(
79             const std::vector<
80                     aidl::android::automotive::watchdog::internal::ResourceOveruseConfiguration>&
81                     configs) = 0;
82     // Returns the existing configurations.
83     virtual void
84     get(std::vector<aidl::android::automotive::watchdog::internal::ResourceOveruseConfiguration>*
85                 resourceOveruseConfigs) const = 0;
86 
87     // Writes the cached configs to disk.
88     virtual android::base::Result<void> writeToDisk() = 0;
89 
90     /**
91      * Returns the list of vendor package prefixes. Any pre-installed package matching one of these
92      * prefixes should be classified as a vendor package.
93      */
94     virtual const std::unordered_set<std::string>& vendorPackagePrefixes() = 0;
95 
96     /**
97      * Returns the package names to application category mappings.
98      */
99     virtual const std::unordered_map<
100             std::string, aidl::android::automotive::watchdog::internal::ApplicationCategoryType>&
101     packagesToAppCategories() = 0;
102 
103     // Fetches the I/O overuse thresholds for the given package.
104     virtual aidl::android::automotive::watchdog::PerStateBytes fetchThreshold(
105             const aidl::android::automotive::watchdog::internal::PackageInfo& packageInfo)
106             const = 0;
107 
108     // Returns whether or not the package is safe to kill on I/O overuse.
109     virtual bool isSafeToKill(const aidl::android::automotive::watchdog::internal::PackageInfo&
110                                       packageInfo) const = 0;
111 
112     struct AlertThresholdHashByDuration {
113     public:
114         size_t operator()(
115                 const aidl::android::automotive::watchdog::internal::IoOveruseAlertThreshold&
116                         threshold) const;
117     };
118 
119     struct AlertThresholdEqualByDuration {
120     public:
121         bool operator()(
122                 const aidl::android::automotive::watchdog::internal::IoOveruseAlertThreshold& l,
123                 const aidl::android::automotive::watchdog::internal::IoOveruseAlertThreshold& r)
124                 const;
125     };
126 
127     using IoOveruseAlertThresholdSet = ::std::unordered_set<
128             aidl::android::automotive::watchdog::internal::IoOveruseAlertThreshold,
129             AlertThresholdHashByDuration, AlertThresholdEqualByDuration>;
130 
131     // Returns system-wide disk I/O overuse thresholds.
132     virtual const IoOveruseAlertThresholdSet& systemWideAlertThresholds() = 0;
133 };
134 
135 class IoOveruseConfigs;
136 
137 /**
138  * ComponentSpecificConfig represents the I/O overuse config defined per component.
139  */
140 class ComponentSpecificConfig final {
141 protected:
ComponentSpecificConfig()142     ComponentSpecificConfig() : mGeneric(defaultThreshold()) {}
143 
~ComponentSpecificConfig()144     ~ComponentSpecificConfig() {
145         mPerPackageThresholds.clear();
146         mSafeToKillPackages.clear();
147     }
148 
149     /**
150      * Updates |mPerPackageThresholds|.
151      */
152     android::base::Result<void> updatePerPackageThresholds(
153             const std::vector<
154                     aidl::android::automotive::watchdog::internal::PerStateIoOveruseThreshold>&
155                     thresholds,
156             const std::function<void(const std::string&)>& maybeAppendVendorPackagePrefixes);
157     /**
158      * Updates |mSafeToKillPackages|.
159      */
160     android::base::Result<void> updateSafeToKillPackages(
161             const std::vector<std::string>& packages,
162             const std::function<void(const std::string&)>& maybeAppendVendorPackagePrefixes);
163 
164     /**
165      * I/O overuse configurations for all packages under the component that are not covered by
166      * |mPerPackageThresholds| or |IoOveruseConfigs.mPerCategoryThresholds|.
167      */
168     aidl::android::automotive::watchdog::internal::PerStateIoOveruseThreshold mGeneric;
169     /**
170      * I/O overuse configurations for specific packages under the component.
171      */
172     std::unordered_map<std::string,
173                        aidl::android::automotive::watchdog::internal::PerStateIoOveruseThreshold>
174             mPerPackageThresholds;
175     /**
176      * List of safe to kill packages under the component in the event of I/O overuse.
177      */
178     std::unordered_set<std::string> mSafeToKillPackages;
179 
180 private:
181     friend class IoOveruseConfigs;
182 };
183 
184 /**
185  * IoOveruseConfigs represents the I/O overuse configuration defined by system and vendor
186  * applications. This class is not thread safe for performance purposes. The caller is responsible
187  * for calling the methods in a thread safe manner.
188  */
189 class IoOveruseConfigs final : public IoOveruseConfigsInterface {
190 public:
191     IoOveruseConfigs();
~IoOveruseConfigs()192     ~IoOveruseConfigs() {
193         mPerCategoryThresholds.clear();
194         mVendorPackagePrefixes.clear();
195         mAlertThresholds.clear();
196     }
197 
198     android::base::Result<void> update(
199             const std::vector<
200                     aidl::android::automotive::watchdog::internal::ResourceOveruseConfiguration>&
201                     configs) override;
202 
203     void
204     get(std::vector<aidl::android::automotive::watchdog::internal::ResourceOveruseConfiguration>*
205                 resourceOveruseConfigs) const override;
206 
207     android::base::Result<void> writeToDisk();
208 
209     aidl::android::automotive::watchdog::PerStateBytes fetchThreshold(
210             const aidl::android::automotive::watchdog::internal::PackageInfo& packageInfo)
211             const override;
212 
213     bool isSafeToKill(const aidl::android::automotive::watchdog::internal::PackageInfo& packageInfo)
214             const override;
215 
systemWideAlertThresholds()216     const IoOveruseAlertThresholdSet& systemWideAlertThresholds() override {
217         return mAlertThresholds;
218     }
219 
vendorPackagePrefixes()220     const std::unordered_set<std::string>& vendorPackagePrefixes() override {
221         return mVendorPackagePrefixes;
222     }
223 
224     const std::unordered_map<
225             std::string, aidl::android::automotive::watchdog::internal::ApplicationCategoryType>&
packagesToAppCategories()226     packagesToAppCategories() override {
227         return mPackagesToAppCategories;
228     }
229 
230 private:
231     enum ConfigUpdateMode {
232         OVERWRITE = 0,
233         MERGE,
234         NO_UPDATE,
235     };
236     android::base::Result<void> updateFromXml(const char* filename);
237 
238     void updateFromAidlConfig(
239             const aidl::android::automotive::watchdog::internal::ResourceOveruseConfiguration&
240                     resourceOveruseConfig);
241 
242     android::base::Result<void> update(
243             const aidl::android::automotive::watchdog::internal::ResourceOveruseConfiguration&
244                     resourceOveruseConfiguration,
245             const aidl::android::automotive::watchdog::internal::IoOveruseConfiguration&
246                     ioOveruseConfiguration,
247             int32_t updatableConfigsFilter, ComponentSpecificConfig* targetComponentConfig);
248 
249     android::base::Result<void> updatePerCategoryThresholds(
250             const std::vector<
251                     aidl::android::automotive::watchdog::internal::PerStateIoOveruseThreshold>&
252                     thresholds);
253     android::base::Result<void> updateAlertThresholds(
254             const std::vector<
255                     aidl::android::automotive::watchdog::internal::IoOveruseAlertThreshold>&
256                     thresholds);
257 
258     std::optional<aidl::android::automotive::watchdog::internal::ResourceOveruseConfiguration> get(
259             const ComponentSpecificConfig& componentSpecificConfig,
260             const int32_t componentFilter) const;
261 
262     // System component specific configuration.
263     ComponentSpecificConfig mSystemConfig;
264     // Vendor component specific configuration.
265     ComponentSpecificConfig mVendorConfig;
266     // Third-party component specific configuration.
267     ComponentSpecificConfig mThirdPartyConfig;
268     // Package name to application category mappings.
269     std::unordered_map<std::string,
270                        aidl::android::automotive::watchdog::internal::ApplicationCategoryType>
271             mPackagesToAppCategories;
272     ConfigUpdateMode mPackagesToAppCategoryMappingUpdateMode;
273     // I/O overuse thresholds per category.
274     std::unordered_map<aidl::android::automotive::watchdog::internal::ApplicationCategoryType,
275                        aidl::android::automotive::watchdog::internal::PerStateIoOveruseThreshold>
276             mPerCategoryThresholds;
277     // List of vendor package prefixes.
278     std::unordered_set<std::string> mVendorPackagePrefixes;
279     // System-wide disk I/O overuse alert thresholds.
280     IoOveruseAlertThresholdSet mAlertThresholds;
281 
282     // For unit tests.
283     using ParseXmlFileFunction = std::function<android::base::Result<
284             aidl::android::automotive::watchdog::internal::ResourceOveruseConfiguration>(
285             const char*)>;
286     using WriteXmlFileFunction = std::function<
287             android::base::Result<void>(const aidl::android::automotive::watchdog::internal::
288                                                 ResourceOveruseConfiguration&,
289                                         const char*)>;
290     static ParseXmlFileFunction sParseXmlFile;
291     static WriteXmlFileFunction sWriteXmlFile;
292 
293     friend class internal::IoOveruseConfigsPeer;
294 };
295 
296 }  // namespace watchdog
297 }  // namespace automotive
298 }  // namespace android
299 
300 #endif  //  CPP_WATCHDOG_SERVER_SRC_IOOVERUSECONFIGS_H_
301