324 lines
12 KiB
C++
324 lines
12 KiB
C++
![]() |
#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
|