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 <optional> 21 #include <set> 22 #include <string> 23 #include <unordered_map> 24 #include <vector> 25 26 #include "androidfw/ConfigDescription.h" 27 #include "androidfw/IDiagnostics.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 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 std::optional<std::string> lang; 58 /** The ISO<?> standard locale region code. */ 59 std::optional<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 std::optional<int> target_sdk_version; 77 std::optional<int> max_sdk_version; 78 std::optional<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<android::ConfigDescription> screen_densities; 113 std::vector<android::ConfigDescription> locales; 114 std::optional<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 /** 129 * XML configuration file parser for the split and optimize commands. 130 */ 131 class ConfigurationParser { 132 public: 133 134 /** Returns a ConfigurationParser for the file located at the provided path. */ 135 static std::optional<ConfigurationParser> ForPath(const std::string& path); 136 137 /** Returns a ConfigurationParser for the configuration in the provided file contents. */ ForContents(const std::string & contents,const std::string & path)138 static ConfigurationParser ForContents(const std::string& contents, const std::string& path) { 139 ConfigurationParser parser{contents, path}; 140 return parser; 141 } 142 143 /** Sets the diagnostics context to use when parsing. */ WithDiagnostics(android::IDiagnostics * diagnostics)144 ConfigurationParser& WithDiagnostics(android::IDiagnostics* diagnostics) { 145 diag_ = diagnostics; 146 return *this; 147 } 148 149 /** 150 * Parses the configuration file and returns the results. If the configuration could not be parsed 151 * the result is empty and any errors will be displayed with the provided diagnostics context. 152 */ 153 std::optional<std::vector<configuration::OutputArtifact>> Parse(android::StringPiece apk_path); 154 155 protected: 156 /** 157 * Instantiates a new ConfigurationParser with the provided configuration file and a no-op 158 * diagnostics context. The default diagnostics context can be overridden with a call to 159 * WithDiagnostics(IDiagnostics *). 160 */ 161 ConfigurationParser(std::string contents, const std::string& config_path); 162 163 /** Returns the current diagnostics context to any subclasses. */ diagnostics()164 android::IDiagnostics* diagnostics() { 165 return diag_; 166 } 167 168 private: 169 /** The contents of the configuration file to parse. */ 170 const std::string contents_; 171 /** Path to the input configuration. */ 172 const std::string config_path_; 173 /** The diagnostics context to send messages to. */ 174 android::IDiagnostics* diag_; 175 }; 176 177 } // namespace aapt 178 179 #endif // AAPT2_CONFIGURATION_H 180