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 <set> 21 #include <string> 22 #include <unordered_map> 23 #include <vector> 24 25 #include "ConfigDescription.h" 26 #include "Diagnostics.h" 27 #include "util/Maybe.h" 28 29 namespace aapt { 30 31 namespace configuration { 32 33 /** Enumeration of currently supported ABIs. */ 34 enum class Abi { 35 kArmeV6, 36 kArmV7a, 37 kArm64V8a, 38 kX86, 39 kX86_64, 40 kMips, 41 kMips64, 42 kUniversal 43 }; 44 45 /** Helper method to convert an ABI to a string representing the path within the APK. */ 46 const android::StringPiece& AbiToString(Abi abi); 47 48 /** 49 * Represents an individual locale. When a locale is included, it must be 50 * declared from least specific to most specific, as a region does not make 51 * sense without a language. If neither the language or region are specified it 52 * acts as a special case for catch all. This can allow all locales to be kept, 53 * or compressed. 54 */ 55 struct Locale { 56 /** The ISO<?> standard locale language code. */ 57 Maybe<std::string> lang; 58 /** The ISO<?> standard locale region code. */ 59 Maybe<std::string> region; 60 61 inline friend bool operator==(const Locale& lhs, const Locale& rhs) { 62 return lhs.lang == rhs.lang && lhs.region == rhs.region; 63 } 64 }; 65 66 // TODO: Encapsulate manifest modifications from the configuration file. 67 struct AndroidManifest { 68 inline friend bool operator==(const AndroidManifest& lhs, const AndroidManifest& rhs) { 69 return true; // nothing to compare yet. 70 } 71 }; 72 73 struct AndroidSdk { 74 std::string label; 75 int min_sdk_version; // min_sdk_version is mandatory if splitting by SDK. 76 Maybe<int> target_sdk_version; 77 Maybe<int> max_sdk_version; 78 Maybe<AndroidManifest> manifest; 79 ForMinSdkAndroidSdk80 static AndroidSdk ForMinSdk(int min_sdk) { 81 AndroidSdk sdk; 82 sdk.min_sdk_version = min_sdk; 83 return sdk; 84 } 85 86 inline friend bool operator==(const AndroidSdk& lhs, const AndroidSdk& rhs) { 87 return lhs.min_sdk_version == rhs.min_sdk_version && 88 lhs.target_sdk_version == rhs.target_sdk_version && 89 lhs.max_sdk_version == rhs.max_sdk_version && 90 lhs.manifest == rhs.manifest; 91 } 92 }; 93 94 // TODO: Make device features more than just an arbitrary string? 95 using DeviceFeature = std::string; 96 97 /** Represents a mapping of texture paths to a GL texture format. */ 98 struct GlTexture { 99 std::string name; 100 std::vector<std::string> texture_paths; 101 102 inline friend bool operator==(const GlTexture& lhs, const GlTexture& rhs) { 103 return lhs.name == rhs.name && lhs.texture_paths == rhs.texture_paths; 104 } 105 }; 106 107 /** An artifact with all the details pulled from the PostProcessingConfiguration. */ 108 struct OutputArtifact { 109 std::string name; 110 int version; 111 std::vector<Abi> abis; 112 std::vector<ConfigDescription> screen_densities; 113 std::vector<ConfigDescription> locales; 114 Maybe<AndroidSdk> android_sdk; 115 std::vector<DeviceFeature> features; 116 std::vector<GlTexture> textures; 117 118 inline int GetMinSdk(int default_value = -1) const { 119 if (!android_sdk) { 120 return default_value; 121 } 122 return android_sdk.value().min_sdk_version; 123 } 124 }; 125 126 } // namespace configuration 127 128 // Forward declaration of classes used in the API. 129 struct IDiagnostics; 130 131 /** 132 * XML configuration file parser for the split and optimize commands. 133 */ 134 class ConfigurationParser { 135 public: 136 137 /** Returns a ConfigurationParser for the file located at the provided path. */ 138 static Maybe<ConfigurationParser> ForPath(const std::string& path); 139 140 /** Returns a ConfigurationParser for the configuration in the provided file contents. */ ForContents(const std::string & contents,const std::string & path)141 static ConfigurationParser ForContents(const std::string& contents, const std::string& path) { 142 ConfigurationParser parser{contents, path}; 143 return parser; 144 } 145 146 /** Sets the diagnostics context to use when parsing. */ WithDiagnostics(IDiagnostics * diagnostics)147 ConfigurationParser& WithDiagnostics(IDiagnostics* diagnostics) { 148 diag_ = diagnostics; 149 return *this; 150 } 151 152 /** 153 * Parses the configuration file and returns the results. If the configuration could not be parsed 154 * the result is empty and any errors will be displayed with the provided diagnostics context. 155 */ 156 Maybe<std::vector<configuration::OutputArtifact>> Parse(const android::StringPiece& apk_path); 157 158 protected: 159 /** 160 * Instantiates a new ConfigurationParser with the provided configuration file and a no-op 161 * diagnostics context. The default diagnostics context can be overridden with a call to 162 * WithDiagnostics(IDiagnostics *). 163 */ 164 ConfigurationParser(std::string contents, const std::string& config_path); 165 166 /** Returns the current diagnostics context to any subclasses. */ diagnostics()167 IDiagnostics* diagnostics() { 168 return diag_; 169 } 170 171 private: 172 /** The contents of the configuration file to parse. */ 173 const std::string contents_; 174 /** Path to the input configuration. */ 175 const std::string config_path_; 176 /** The diagnostics context to send messages to. */ 177 IDiagnostics* diag_; 178 }; 179 180 } // namespace aapt 181 182 #endif // AAPT2_CONFIGURATION_H 183