1 /* 2 * Copyright 2023 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 <optional> 20 #include <string> 21 #include <unordered_map> 22 #include <utility> 23 24 #include "android-base/macros.h" 25 #include "cmd/Util.h" 26 #include "process/IResourceTableConsumer.h" 27 28 namespace aapt { 29 30 struct FeatureFlagsFilterOptions { 31 // If true, elements whose featureFlag values are false (i.e., disabled feature) will be removed. 32 bool remove_disabled_elements = true; 33 34 // If true, `Consume()` will return false (error) if a flag was found that is not in 35 // `feature_flag_values`. 36 bool fail_on_unrecognized_flags = true; 37 38 // If true, `Consume()` will return false (error) if a flag was found whose value in 39 // `feature_flag_values` is not defined (std::nullopt). 40 bool flags_must_have_value = true; 41 42 // If true, `Consume()` will return false (error) if a flag was found whose value in 43 // `feature_flag_values` is not readonly. 44 bool flags_must_be_readonly = false; 45 }; 46 47 // Looks for the `android:featureFlag` attribute in each XML element, validates the flag names and 48 // values, and removes elements according to the values in `feature_flag_values`. An element will be 49 // removed if the flag's given value is FALSE. A "!" before the flag name in the attribute indicates 50 // a boolean NOT operation, i.e., an element will be removed if the flag's given value is TRUE. For 51 // example, if the XML is the following: 52 // 53 // <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> 54 // <permission android:name="FOO" android:featureFlag="!flag" 55 // android:protectionLevel="normal" /> 56 // <permission android:name="FOO" android:featureFlag="flag" 57 // android:protectionLevel="dangerous" /> 58 // </manifest> 59 // 60 // If `feature_flag_values` contains {"flag", true}, then the <permission> element with 61 // protectionLevel="normal" will be removed, and the <permission> element with 62 // protectionLevel="normal" will be kept. 63 // 64 // The `Consume()` function will return false if there is an invalid flag found (see 65 // FeatureFlagsFilterOptions for customizing the filter's validation behavior). Do not use the XML 66 // further if there are errors as there may be elements removed already. 67 class FeatureFlagsFilter : public IXmlResourceConsumer { 68 public: FeatureFlagsFilter(FeatureFlagValues feature_flag_values,FeatureFlagsFilterOptions options)69 explicit FeatureFlagsFilter(FeatureFlagValues feature_flag_values, 70 FeatureFlagsFilterOptions options) 71 : feature_flag_values_(std::move(feature_flag_values)), options_(options) { 72 } 73 74 bool Consume(IAaptContext* context, xml::XmlResource* doc) override; 75 76 private: 77 DISALLOW_COPY_AND_ASSIGN(FeatureFlagsFilter); 78 79 const FeatureFlagValues feature_flag_values_; 80 const FeatureFlagsFilterOptions options_; 81 }; 82 83 } // namespace aapt 84