blob: f079665f13d5696c42ede1e2931d8ac96ca3809d [file] [log] [blame]
#define LOG_TAG "com.android.apex"
#include "com_android_apex.h"
#include <assert.h>
#ifndef __BIONIC__
#define __assert2(f,n,fun,e) do { fprintf(stderr, "%s:%d: %s: Assertion `%s' failed", (f), (n), (fun), (e)); abort(); } while (false)
#endif
#define _xsdc_assert(e) do if (!(e)) __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, #e); while (false)
namespace com {
namespace android {
namespace apex {
template <class T>
constexpr void (*xmlDeleter)(T* t);
template <>
constexpr auto xmlDeleter<xmlDoc> = xmlFreeDoc;
template <>
auto xmlDeleter<xmlChar> = [](xmlChar *s) { xmlFree(s); };
template <class T>
constexpr auto make_xmlUnique(T *t) {
auto deleter = [](T *t) { xmlDeleter<T>(t); };
return std::unique_ptr<T, decltype(deleter)>{t, deleter};
}
static std::string getXmlAttribute(const xmlNode *cur, const char *attribute) {
auto xmlValue = make_xmlUnique(xmlGetProp(cur, reinterpret_cast<const xmlChar*>(attribute)));
if (xmlValue == nullptr) {
return "";
}
std::string value(reinterpret_cast<const char*>(xmlValue.get()));
return value;
}
std::optional<ApexInfoList> readApexInfoList(const char* configFile) {
auto doc = make_xmlUnique(xmlParseFile(configFile));
if (doc == nullptr) {
return std::nullopt;
}
xmlNodePtr _child = xmlDocGetRootElement(doc.get());
if (_child == nullptr) {
return std::nullopt;
}
if (xmlXIncludeProcess(doc.get()) < 0) {
return std::nullopt;
}
if (!xmlStrcmp(_child->name, reinterpret_cast<const xmlChar*>("apex-info-list"))) {
ApexInfoList _value = ApexInfoList::read(_child);
return _value;
}
return std::nullopt;
}
std::optional<ApexInfoList> parseApexInfoList(const char* xml) {
auto doc = make_xmlUnique(xmlParseDoc(reinterpret_cast<const xmlChar*>(xml)));
if (doc == nullptr) {
return std::nullopt;
}
xmlNodePtr _child = xmlDocGetRootElement(doc.get());
if (_child == nullptr) {
return std::nullopt;
}
if (xmlXIncludeProcess(doc.get()) < 0) {
return std::nullopt;
}
if (!xmlStrcmp(_child->name, reinterpret_cast<const xmlChar*>("apex-info-list"))) {
ApexInfoList _value = ApexInfoList::read(_child);
return _value;
}
return std::nullopt;
}
void write(std::ostream& _out, const ApexInfoList& apexInfoList) {
_out << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
apexInfoList.write(_out, "apex-info-list");
}
static int indentIndex = 0;
std::string printIndent() {
std::string s = "";
for (int index = 0; index < indentIndex; ++index) {
s += " ";
}
return s;
}
ApexInfoList::ApexInfoList(std::vector<ApexInfo> apexInfo) : apexInfo_(std::move(apexInfo)) {
}
const std::vector<ApexInfo>& ApexInfoList::getApexInfo() const {
return apexInfo_;
}
bool ApexInfoList::hasApexInfo() const {
return !(apexInfo_.empty());
}
const ApexInfo* ApexInfoList::getFirstApexInfo() const {
if (apexInfo_.empty()) {
return nullptr;
}
return &apexInfo_[0];
}
ApexInfoList ApexInfoList::read(xmlNode *root) {
std::string _raw;
std::vector<ApexInfo> apexInfo;
for (auto *_child = root->xmlChildrenNode; _child != nullptr; _child = _child->next) {
if (!xmlStrcmp(_child->name, reinterpret_cast<const xmlChar*>("apex-info"))) {
ApexInfo _value = ApexInfo::read(_child);
apexInfo.push_back(std::move(_value));
}
}
ApexInfoList instance(apexInfo);
return instance;
}
void ApexInfoList::write(std::ostream& _out, const std::string& _name) const {
_out << printIndent() << "<" << _name;
_out << ">" << std::endl;
++indentIndex;
for (auto& _value : getApexInfo()) {
_value.write(_out, "apex-info");
}
--indentIndex;
_out << printIndent() << "</" << _name << ">" << std::endl;
}
ApexInfo::ApexInfo(std::string moduleName, std::string modulePath, std::optional<std::string> preinstalledModulePath, int64_t versionCode, std::string versionName, bool isFactory, bool isActive, std::optional<int64_t> lastUpdateMillis, bool provideSharedApexLibs) : moduleName_(std::move(moduleName)), modulePath_(std::move(modulePath)), preinstalledModulePath_(std::move(preinstalledModulePath)), versionCode_(versionCode), versionName_(std::move(versionName)), isFactory_(isFactory), isActive_(isActive), lastUpdateMillis_(lastUpdateMillis), provideSharedApexLibs_(provideSharedApexLibs) {
}
const std::string& ApexInfo::getModuleName() const {
return moduleName_;
}
bool ApexInfo::hasModuleName() const {
return true;
}
const std::string& ApexInfo::getModulePath() const {
return modulePath_;
}
bool ApexInfo::hasModulePath() const {
return true;
}
const std::string& ApexInfo::getPreinstalledModulePath() const {
_xsdc_assert(hasPreinstalledModulePath());
return preinstalledModulePath_.value();
}
bool ApexInfo::hasPreinstalledModulePath() const {
return preinstalledModulePath_.has_value();
}
const int64_t& ApexInfo::getVersionCode() const {
return versionCode_;
}
bool ApexInfo::hasVersionCode() const {
return true;
}
const std::string& ApexInfo::getVersionName() const {
return versionName_;
}
bool ApexInfo::hasVersionName() const {
return true;
}
const bool& ApexInfo::getIsFactory() const {
return isFactory_;
}
bool ApexInfo::hasIsFactory() const {
return true;
}
const bool& ApexInfo::getIsActive() const {
return isActive_;
}
bool ApexInfo::hasIsActive() const {
return true;
}
const int64_t& ApexInfo::getLastUpdateMillis() const {
_xsdc_assert(hasLastUpdateMillis());
return lastUpdateMillis_.value();
}
bool ApexInfo::hasLastUpdateMillis() const {
return lastUpdateMillis_.has_value();
}
const bool& ApexInfo::getProvideSharedApexLibs() const {
return provideSharedApexLibs_;
}
bool ApexInfo::hasProvideSharedApexLibs() const {
return true;
}
ApexInfo ApexInfo::read(xmlNode *root) {
std::string _raw;
_raw = getXmlAttribute(root, "moduleName");
std::string moduleName{};
if (_raw != "") {
std::string &_value = _raw;
moduleName = _value;
}
_raw = getXmlAttribute(root, "modulePath");
std::string modulePath{};
if (_raw != "") {
std::string &_value = _raw;
modulePath = _value;
}
_raw = getXmlAttribute(root, "preinstalledModulePath");
std::optional<std::string> preinstalledModulePath = std::nullopt;
if (_raw != "") {
std::string &_value = _raw;
preinstalledModulePath = _value;
}
_raw = getXmlAttribute(root, "versionCode");
int64_t versionCode{};
if (_raw != "") {
int64_t _value = std::stoll(_raw);
versionCode = _value;
}
_raw = getXmlAttribute(root, "versionName");
std::string versionName{};
if (_raw != "") {
std::string &_value = _raw;
versionName = _value;
}
_raw = getXmlAttribute(root, "isFactory");
bool isFactory{};
if (_raw != "") {
bool _value = _raw == "true";
isFactory = _value;
}
_raw = getXmlAttribute(root, "isActive");
bool isActive{};
if (_raw != "") {
bool _value = _raw == "true";
isActive = _value;
}
_raw = getXmlAttribute(root, "lastUpdateMillis");
std::optional<int64_t> lastUpdateMillis = std::nullopt;
if (_raw != "") {
int64_t _value = std::stoll(_raw);
lastUpdateMillis = _value;
}
_raw = getXmlAttribute(root, "provideSharedApexLibs");
bool provideSharedApexLibs{};
if (_raw != "") {
bool _value = _raw == "true";
provideSharedApexLibs = _value;
}
ApexInfo instance(moduleName, modulePath, preinstalledModulePath, versionCode, versionName, isFactory, isActive, lastUpdateMillis, provideSharedApexLibs);
return instance;
}
void ApexInfo::write(std::ostream& _out, const std::string& _name) const {
_out << printIndent() << "<" << _name;
if (hasModuleName()) {
_out << " moduleName=\"";
_out << getModuleName();
_out << "\"";
}
if (hasModulePath()) {
_out << " modulePath=\"";
_out << getModulePath();
_out << "\"";
}
if (hasPreinstalledModulePath()) {
_out << " preinstalledModulePath=\"";
_out << getPreinstalledModulePath();
_out << "\"";
}
if (hasVersionCode()) {
_out << " versionCode=\"";
_out << getVersionCode();
_out << "\"";
}
if (hasVersionName()) {
_out << " versionName=\"";
_out << getVersionName();
_out << "\"";
}
if (hasIsFactory()) {
_out << " isFactory=\"";
_out << (getIsFactory() ? "true" : "false");
_out << "\"";
}
if (hasIsActive()) {
_out << " isActive=\"";
_out << (getIsActive() ? "true" : "false");
_out << "\"";
}
if (hasLastUpdateMillis()) {
_out << " lastUpdateMillis=\"";
_out << getLastUpdateMillis();
_out << "\"";
}
if (hasProvideSharedApexLibs()) {
_out << " provideSharedApexLibs=\"";
_out << (getProvideSharedApexLibs() ? "true" : "false");
_out << "\"";
}
_out << ">" << std::endl;
++indentIndex;
--indentIndex;
_out << printIndent() << "</" << _name << ">" << std::endl;
}
} // apex
} // android
} // com