1 /* 2 * Copyright (C) 2017 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 AAPT2_CONFIGURATION_H 18 #define AAPT2_CONFIGURATION_H 19 20 #include <string> 21 #include <unordered_map> 22 #include <vector> 23 24 #include "ConfigDescription.h" 25 #include "Diagnostics.h" 26 #include "util/Maybe.h" 27 28 namespace aapt { 29 30 namespace configuration { 31 32 /** A mapping of group labels to group of configuration items. */ 33 template<class T> 34 using Group = std::unordered_map<std::string, std::vector<T>>; 35 36 /** Output artifact configuration options. */ 37 struct Artifact { 38 /** Name to use for output of processing foo.apk -> foo.<name>.apk. */ 39 std::string name; 40 /** If present, uses the ABI group with this name. */ 41 Maybe<std::string> abi_group; 42 /** If present, uses the screen density group with this name. */ 43 Maybe<std::string> screen_density_group; 44 /** If present, uses the locale group with this name. */ 45 Maybe<std::string> locale_group; 46 /** If present, uses the Android SDK group with this name. */ 47 Maybe<std::string> android_sdk_group; 48 /** If present, uses the device feature group with this name. */ 49 Maybe<std::string> device_feature_group; 50 /** If present, uses the OpenGL texture group with this name. */ 51 Maybe<std::string> gl_texture_group; 52 53 /** Convert an artifact name template into a name string based on configuration contents. */ 54 Maybe<std::string> ToArtifactName(const std::string& format, IDiagnostics* diag) const; 55 }; 56 57 /** Enumeration of currently supported ABIs. */ 58 enum class Abi { 59 kArmeV6, 60 kArmV7a, 61 kArm64V8a, 62 kX86, 63 kX86_64, 64 kMips, 65 kMips64, 66 kUniversal 67 }; 68 69 /** Helper method to convert an ABI to a string representing the path within the APK. */ 70 const std::string& AbiToString(Abi abi); 71 72 /** 73 * Represents an individual locale. When a locale is included, it must be 74 * declared from least specific to most specific, as a region does not make 75 * sense without a language. If neither the language or region are specified it 76 * acts as a special case for catch all. This can allow all locales to be kept, 77 * or compressed. 78 */ 79 struct Locale { 80 /** The ISO<?> standard locale language code. */ 81 Maybe<std::string> lang; 82 /** The ISO<?> standard locale region code. */ 83 Maybe<std::string> region; 84 85 inline friend bool operator==(const Locale& lhs, const Locale& rhs) { 86 return lhs.lang == rhs.lang && lhs.region == rhs.region; 87 } 88 }; 89 90 // TODO: Encapsulate manifest modifications from the configuration file. 91 struct AndroidManifest { 92 inline friend bool operator==(const AndroidManifest& lhs, const AndroidManifest& rhs) { 93 return true; // nothing to compare yet. 94 } 95 }; 96 97 struct AndroidSdk { 98 Maybe<std::string> min_sdk_version; 99 Maybe<std::string> target_sdk_version; 100 Maybe<std::string> max_sdk_version; 101 Maybe<AndroidManifest> manifest; 102 103 inline friend bool operator==(const AndroidSdk& lhs, const AndroidSdk& rhs) { 104 return lhs.min_sdk_version == rhs.min_sdk_version && 105 lhs.target_sdk_version == rhs.target_sdk_version && 106 lhs.max_sdk_version == rhs.max_sdk_version && 107 lhs.manifest == rhs.manifest; 108 } 109 }; 110 111 // TODO: Make device features more than just an arbitrary string? 112 using DeviceFeature = std::string; 113 114 /** Represents a mapping of texture paths to a GL texture format. */ 115 struct GlTexture { 116 std::string name; 117 std::vector<std::string> texture_paths; 118 119 inline friend bool operator==(const GlTexture& lhs, const GlTexture& rhs) { 120 return lhs.name == rhs.name && lhs.texture_paths == rhs.texture_paths; 121 } 122 }; 123 124 /** AAPT2 XML configuration file binary representation. */ 125 struct PostProcessingConfiguration { 126 // TODO: Support named artifacts? 127 std::vector<Artifact> artifacts; 128 Maybe<std::string> artifact_format; 129 130 Group<Abi> abi_groups; 131 Group<ConfigDescription> screen_density_groups; 132 Group<Locale> locale_groups; 133 Group<AndroidSdk> android_sdk_groups; 134 Group<DeviceFeature> device_feature_groups; 135 Group<GlTexture> gl_texture_groups; 136 }; 137 138 } // namespace configuration 139 140 // Forward declaration of classes used in the API. 141 struct IDiagnostics; 142 namespace xml { 143 class Element; 144 } 145 146 /** 147 * XML configuration file parser for the split and optimize commands. 148 */ 149 class ConfigurationParser { 150 public: 151 152 /** Returns a ConfigurationParser for the file located at the provided path. */ 153 static Maybe<ConfigurationParser> ForPath(const std::string& path); 154 155 /** Returns a ConfigurationParser for the configuration in the provided file contents. */ ForContents(const std::string & contents)156 static ConfigurationParser ForContents(const std::string& contents) { 157 ConfigurationParser parser{contents}; 158 return parser; 159 } 160 161 /** Sets the diagnostics context to use when parsing. */ WithDiagnostics(IDiagnostics * diagnostics)162 ConfigurationParser& WithDiagnostics(IDiagnostics* diagnostics) { 163 diag_ = diagnostics; 164 return *this; 165 } 166 167 /** 168 * Parses the configuration file and returns the results. If the configuration could not be parsed 169 * the result is empty and any errors will be displayed with the provided diagnostics context. 170 */ 171 Maybe<configuration::PostProcessingConfiguration> Parse(); 172 173 protected: 174 /** 175 * Instantiates a new ConfigurationParser with the provided configuration file and a no-op 176 * diagnostics context. The default diagnostics context can be overridden with a call to 177 * WithDiagnostics(IDiagnostics *). 178 */ 179 explicit ConfigurationParser(std::string contents); 180 181 /** Returns the current diagnostics context to any subclasses. */ diagnostics()182 IDiagnostics* diagnostics() { 183 return diag_; 184 } 185 186 /** 187 * An ActionHandler for processing XML elements in the XmlActionExecutor. Returns true if the 188 * element was successfully processed, otherwise returns false. 189 */ 190 using ActionHandler = std::function<bool(configuration::PostProcessingConfiguration* config, 191 xml::Element* element, IDiagnostics* diag)>; 192 193 /** Handler for <artifact> tags. */ 194 static ActionHandler artifact_handler_; 195 /** Handler for <artifact-format> tags. */ 196 static ActionHandler artifact_format_handler_; 197 /** Handler for <abi-group> tags. */ 198 static ActionHandler abi_group_handler_; 199 /** Handler for <screen-density-group> tags. */ 200 static ActionHandler screen_density_group_handler_; 201 /** Handler for <locale-group> tags. */ 202 static ActionHandler locale_group_handler_; 203 /** Handler for <android-sdk-group> tags. */ 204 static ActionHandler android_sdk_group_handler_; 205 /** Handler for <gl-texture-group> tags. */ 206 static ActionHandler gl_texture_group_handler_; 207 /** Handler for <device-feature-group> tags. */ 208 static ActionHandler device_feature_group_handler_; 209 210 private: 211 /** The contents of the configuration file to parse. */ 212 const std::string contents_; 213 /** The diagnostics context to send messages to. */ 214 IDiagnostics* diag_; 215 }; 216 217 } // namespace aapt 218 219 #endif // AAPT2_CONFIGURATION_H 220