Sort output artifacts so that the updated versionCode manifest entry will allow correct handling of updates from Play Store. The most important dimension is Android SDK version. It is important that a split based on min SDK version will allow a user to get a new APK if they upgrade the OS on their device to support a new split. ABI splits need to also be taken into consideration as it is possible for a device to run in ARM emulation mode and installing an ARM APK over a x86 APK could cause performance regressions. The XML file format was updated to give each of the configuration groups have their own section of the XML file. This allows the sort order to be determined by a groups ordering. Artifacts can now be added to the configuration file in an arbitrary order. Since this will be the common case for developers, it will help reduce errors from inserting a new artifact in the wrong spot. The implementation follows the rules outlined at: https://developer.android.com/google/play/publishing/multiple-apks.html Test: Unit tests Test: Manual process XML configuration Change-Id: I0face862c6d6b9d3cd2d99088afe5b9491be0120
183 lines
5.4 KiB
C++
183 lines
5.4 KiB
C++
/*
|
|
* Copyright (C) 2017 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef AAPT2_CONFIGURATION_H
|
|
#define AAPT2_CONFIGURATION_H
|
|
|
|
#include <set>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
#include "ConfigDescription.h"
|
|
#include "Diagnostics.h"
|
|
#include "util/Maybe.h"
|
|
|
|
namespace aapt {
|
|
|
|
namespace configuration {
|
|
|
|
/** Enumeration of currently supported ABIs. */
|
|
enum class Abi {
|
|
kArmeV6,
|
|
kArmV7a,
|
|
kArm64V8a,
|
|
kX86,
|
|
kX86_64,
|
|
kMips,
|
|
kMips64,
|
|
kUniversal
|
|
};
|
|
|
|
/** Helper method to convert an ABI to a string representing the path within the APK. */
|
|
const android::StringPiece& AbiToString(Abi abi);
|
|
|
|
/**
|
|
* Represents an individual locale. When a locale is included, it must be
|
|
* declared from least specific to most specific, as a region does not make
|
|
* sense without a language. If neither the language or region are specified it
|
|
* acts as a special case for catch all. This can allow all locales to be kept,
|
|
* or compressed.
|
|
*/
|
|
struct Locale {
|
|
/** The ISO<?> standard locale language code. */
|
|
Maybe<std::string> lang;
|
|
/** The ISO<?> standard locale region code. */
|
|
Maybe<std::string> region;
|
|
|
|
inline friend bool operator==(const Locale& lhs, const Locale& rhs) {
|
|
return lhs.lang == rhs.lang && lhs.region == rhs.region;
|
|
}
|
|
};
|
|
|
|
// TODO: Encapsulate manifest modifications from the configuration file.
|
|
struct AndroidManifest {
|
|
inline friend bool operator==(const AndroidManifest& lhs, const AndroidManifest& rhs) {
|
|
return true; // nothing to compare yet.
|
|
}
|
|
};
|
|
|
|
struct AndroidSdk {
|
|
std::string label;
|
|
int min_sdk_version; // min_sdk_version is mandatory if splitting by SDK.
|
|
Maybe<int> target_sdk_version;
|
|
Maybe<int> max_sdk_version;
|
|
Maybe<AndroidManifest> manifest;
|
|
|
|
static AndroidSdk ForMinSdk(int min_sdk) {
|
|
AndroidSdk sdk;
|
|
sdk.min_sdk_version = min_sdk;
|
|
return sdk;
|
|
}
|
|
|
|
inline friend bool operator==(const AndroidSdk& lhs, const AndroidSdk& rhs) {
|
|
return lhs.min_sdk_version == rhs.min_sdk_version &&
|
|
lhs.target_sdk_version == rhs.target_sdk_version &&
|
|
lhs.max_sdk_version == rhs.max_sdk_version &&
|
|
lhs.manifest == rhs.manifest;
|
|
}
|
|
};
|
|
|
|
// TODO: Make device features more than just an arbitrary string?
|
|
using DeviceFeature = std::string;
|
|
|
|
/** Represents a mapping of texture paths to a GL texture format. */
|
|
struct GlTexture {
|
|
std::string name;
|
|
std::vector<std::string> texture_paths;
|
|
|
|
inline friend bool operator==(const GlTexture& lhs, const GlTexture& rhs) {
|
|
return lhs.name == rhs.name && lhs.texture_paths == rhs.texture_paths;
|
|
}
|
|
};
|
|
|
|
/** An artifact with all the details pulled from the PostProcessingConfiguration. */
|
|
struct OutputArtifact {
|
|
std::string name;
|
|
int version;
|
|
std::vector<Abi> abis;
|
|
std::vector<ConfigDescription> screen_densities;
|
|
std::vector<ConfigDescription> locales;
|
|
Maybe<AndroidSdk> android_sdk;
|
|
std::vector<DeviceFeature> features;
|
|
std::vector<GlTexture> textures;
|
|
|
|
inline int GetMinSdk(int default_value = -1) const {
|
|
if (!android_sdk) {
|
|
return default_value;
|
|
}
|
|
return android_sdk.value().min_sdk_version;
|
|
}
|
|
};
|
|
|
|
} // namespace configuration
|
|
|
|
// Forward declaration of classes used in the API.
|
|
struct IDiagnostics;
|
|
|
|
/**
|
|
* XML configuration file parser for the split and optimize commands.
|
|
*/
|
|
class ConfigurationParser {
|
|
public:
|
|
|
|
/** Returns a ConfigurationParser for the file located at the provided path. */
|
|
static Maybe<ConfigurationParser> ForPath(const std::string& path);
|
|
|
|
/** Returns a ConfigurationParser for the configuration in the provided file contents. */
|
|
static ConfigurationParser ForContents(const std::string& contents, const std::string& path) {
|
|
ConfigurationParser parser{contents, path};
|
|
return parser;
|
|
}
|
|
|
|
/** Sets the diagnostics context to use when parsing. */
|
|
ConfigurationParser& WithDiagnostics(IDiagnostics* diagnostics) {
|
|
diag_ = diagnostics;
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* Parses the configuration file and returns the results. If the configuration could not be parsed
|
|
* the result is empty and any errors will be displayed with the provided diagnostics context.
|
|
*/
|
|
Maybe<std::vector<configuration::OutputArtifact>> Parse(const android::StringPiece& apk_path);
|
|
|
|
protected:
|
|
/**
|
|
* Instantiates a new ConfigurationParser with the provided configuration file and a no-op
|
|
* diagnostics context. The default diagnostics context can be overridden with a call to
|
|
* WithDiagnostics(IDiagnostics *).
|
|
*/
|
|
ConfigurationParser(std::string contents, const std::string& config_path);
|
|
|
|
/** Returns the current diagnostics context to any subclasses. */
|
|
IDiagnostics* diagnostics() {
|
|
return diag_;
|
|
}
|
|
|
|
private:
|
|
/** The contents of the configuration file to parse. */
|
|
const std::string contents_;
|
|
/** Path to the input configuration. */
|
|
const std::string config_path_;
|
|
/** The diagnostics context to send messages to. */
|
|
IDiagnostics* diag_;
|
|
};
|
|
|
|
} // namespace aapt
|
|
|
|
#endif // AAPT2_CONFIGURATION_H
|