1 #include <boost/algorithm/string/find.hpp> 2 #include <boost/filesystem.hpp> 3 #include <forward_list> 5 #include "androidmanager.h" 6 #include "packagemanagerfactory.h" 8 #include "utilities/utils.h" 10 #include <boost/phoenix/stl/algorithm/transformation.hpp> 11 #include <boost/spirit/include/phoenix_container.hpp> 12 #include <boost/spirit/include/phoenix_core.hpp> 13 #include <boost/spirit/include/qi.hpp> 15 namespace qi = boost::spirit::qi;
18 const std::string AndroidManager::data_ota_package_dir_ =
"/data/ota_package";
20 AUTO_REGISTER_PACKAGE_MANAGER(PACKAGE_MANAGER_ANDROID,
AndroidManager);
22 Json::Value AndroidManager::getInstalledPackages()
const {
23 using boost::phoenix::copy;
27 std::string pm_output;
28 Json::Value packages(Json::arrayValue);
29 if (0 != Utils::shell(
"pm list packages --show-versioncode", &pm_output)) {
33 qi::rule<std::string::iterator, std::vector<char>()> char_seq = qi::lexeme[*(char_ -
' ')];
35 std::istringstream pv_lines(pm_output);
36 for (std::string line; std::getline(pv_lines, line);) {
39 if (qi::parse(line.begin(), line.end(),
40 (
"package:" >> char_seq[copy(_1, std::back_inserter(p))] >>
' ' >>
"versionCode:" >>
41 char_seq[copy(_1, std::back_inserter(v))]))) {
44 package[
"version"] = v;
45 packages.append(package);
52 using boost::phoenix::push_front;
53 using boost::spirit::ascii::xdigit;
56 std::string getprop_output;
57 if (0 == Utils::shell(
"getprop ota.last_installed_package_file", &getprop_output)) {
58 std::forward_list<char> hash;
59 qi::phrase_parse(getprop_output.crbegin(), getprop_output.crend(),
60 *(xdigit[push_front(boost::phoenix::ref(hash), _1)]), boost::spirit::ascii::cntrl);
61 std::vector<Uptane::Target> installed_versions;
62 storage_->loadPrimaryInstallationLog(&installed_versions,
false);
63 for (
const auto& target : installed_versions) {
64 if (std::equal(hash.cbegin(), hash.cend(), target.sha256Hash().cbegin())) {
69 return Uptane::Target::Unknown();
73 LOG_INFO <<
"Begin Android package installation";
74 auto package_filename = (fs::path(data_ota_package_dir_) / target.filename()).
string() +
"." + target.sha256Hash();
75 std::ofstream package_file(package_filename.c_str());
76 if (!package_file.good()) {
77 throw std::runtime_error(std::string(
"Error opening file ") + package_filename);
79 package_file << *storage_->openTargetFile(target);
81 if (bootloader_ !=
nullptr) {
82 bootloader_->rebootFlagSet();
84 LOG_INFO <<
"Performing sync()";
90 std::string ota_package_file_path = GetOTAPackageFilePath(target.sha256Hash());
91 if (!ota_package_file_path.empty()) {
92 fs::remove(ota_package_file_path);
94 std::string errorMessage{
"n/a"};
95 if (installationAborted(&errorMessage)) {
101 std::string AndroidManager::GetOTAPackageFilePath(
const std::string& hash) {
102 fs::directory_iterator entryItEnd;
103 fs::directory_iterator entryIt{fs::path(data_ota_package_dir_)};
104 for (; entryIt != entryItEnd; ++entryIt) {
105 auto& entry_path = entryIt->path();
106 if (boost::filesystem::is_directory(*entryIt)) {
109 auto ext = entry_path.extension().string();
112 return entry_path.string();
115 return std::string{};
118 bool AndroidManager::installationAborted(std::string* errorMessage)
const {
119 std::string installation_log_file{
"/cache/recovery/last_install"};
120 std::ifstream log(installation_log_file.c_str());
122 throw std::runtime_error(std::string(
"Error opening file ") + installation_log_file);
124 for (std::string line; std::getline(log, line);) {
125 if (!boost::algorithm::find_first(line,
"error:").empty()) {
126 int error_code = std::stoi(line.substr(6));
127 if (error_code != 0) {
128 *errorMessage = std::string(
"Error code: ") + std::to_string(error_code);
Package installation failed.