#define LOG_TAG "com.android.apex" #include "com_android_apex.h" #include #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 constexpr void (*xmlDeleter)(T* t); template <> constexpr auto xmlDeleter = xmlFreeDoc; template <> auto xmlDeleter = [](xmlChar *s) { xmlFree(s); }; template constexpr auto make_xmlUnique(T *t) { auto deleter = [](T *t) { xmlDeleter(t); }; return std::unique_ptr{t, deleter}; } static std::string getXmlAttribute(const xmlNode *cur, const char *attribute) { auto xmlValue = make_xmlUnique(xmlGetProp(cur, reinterpret_cast(attribute))); if (xmlValue == nullptr) { return ""; } std::string value(reinterpret_cast(xmlValue.get())); return value; } std::optional 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("apex-info-list"))) { ApexInfoList _value = ApexInfoList::read(_child); return _value; } return std::nullopt; } std::optional parseApexInfoList(const char* xml) { auto doc = make_xmlUnique(xmlParseDoc(reinterpret_cast(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("apex-info-list"))) { ApexInfoList _value = ApexInfoList::read(_child); return _value; } return std::nullopt; } void write(std::ostream& _out, const ApexInfoList& apexInfoList) { _out << "\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_(std::move(apexInfo)) { } const std::vector& 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; for (auto *_child = root->xmlChildrenNode; _child != nullptr; _child = _child->next) { if (!xmlStrcmp(_child->name, reinterpret_cast("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() << "" << std::endl; } ApexInfo::ApexInfo(std::string moduleName, std::string modulePath, std::optional preinstalledModulePath, int64_t versionCode, std::string versionName, bool isFactory, bool isActive, std::optional 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 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 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() << "" << std::endl; } } // apex } // android } // com