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