Aktualizr
C++ SOTA Client
All Classes Namespaces Files Functions Variables Enumerations Enumerator Pages
androidmanager.cc
1 #include <boost/algorithm/string/find.hpp>
2 #include <boost/filesystem.hpp>
3 #include <forward_list>
4 
5 #include "androidmanager.h"
6 #include "packagemanagerfactory.h"
7 
8 #include "utilities/utils.h"
9 
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>
14 
15 namespace qi = boost::spirit::qi;
16 namespace fs = boost::filesystem;
17 
18 const std::string AndroidManager::data_ota_package_dir_ = "/data/ota_package";
19 
20 AUTO_REGISTER_PACKAGE_MANAGER(PACKAGE_MANAGER_ANDROID, AndroidManager);
21 
22 Json::Value AndroidManager::getInstalledPackages() const {
23  using boost::phoenix::copy;
24  using qi::_1;
25  using qi::char_;
26 
27  std::string pm_output;
28  Json::Value packages(Json::arrayValue);
29  if (0 != Utils::shell("pm list packages --show-versioncode", &pm_output)) {
30  return packages;
31  }
32 
33  qi::rule<std::string::iterator, std::vector<char>()> char_seq = qi::lexeme[*(char_ - ' ')];
34 
35  std::istringstream pv_lines(pm_output);
36  for (std::string line; std::getline(pv_lines, line);) {
37  std::string p, v;
38  if (qi::parse(line.begin(), line.end(),
39  ("package:" >> char_seq[copy(_1, std::back_inserter(p))] >> ' ' >> "versionCode:" >>
40  char_seq[copy(_1, std::back_inserter(v))]))) {
41  Json::Value package;
42  package["name"] = p;
43  package["version"] = v;
44  packages.append(package);
45  }
46  }
47  return packages;
48 }
49 
50 Uptane::Target AndroidManager::getCurrent() const {
51  using boost::phoenix::push_front;
52  using boost::spirit::ascii::xdigit;
53  using qi::_1;
54 
55  std::string getprop_output;
56  if (0 == Utils::shell("getprop ota.last_installed_package_file", &getprop_output)) {
57  std::forward_list<char> hash;
58  qi::phrase_parse(getprop_output.crbegin(), getprop_output.crend(),
59  *(xdigit[push_front(boost::phoenix::ref(hash), _1)]), boost::spirit::ascii::cntrl);
60  std::vector<Uptane::Target> installed_versions;
61  storage_->loadPrimaryInstallationLog(&installed_versions, false);
62  for (const auto& target : installed_versions) {
63  if (std::equal(hash.cbegin(), hash.cend(), target.sha256Hash().cbegin())) {
64  return target;
65  }
66  }
67  }
68  return Uptane::Target::Unknown();
69 }
70 
71 data::InstallationResult AndroidManager::install(const Uptane::Target& target) const {
72  LOG_INFO << "Begin Android package installation";
73  auto package_filename = (fs::path(data_ota_package_dir_) / target.filename()).string() + "." + target.sha256Hash();
74  std::ofstream package_file(package_filename.c_str());
75  if (!package_file.good()) {
76  throw std::runtime_error(std::string("Error opening file ") + package_filename);
77  }
78  package_file << *storage_->openTargetFile(target);
79 
80  if (bootloader_ != nullptr) {
81  bootloader_->rebootFlagSet();
82  }
83  LOG_INFO << "Performing sync()";
84  sync();
85  return data::InstallationResult(data::ResultCode::Numeric::kNeedCompletion, "need reboot");
86 }
87 
88 data::InstallationResult AndroidManager::finalizeInstall(const Uptane::Target& target) const {
89  std::string ota_package_file_path = GetOTAPackageFilePath(target.sha256Hash());
90  if (!ota_package_file_path.empty()) fs::remove(ota_package_file_path);
91  std::string errorMessage{"n/a"};
92  if (installationAborted(&errorMessage)) {
94  }
95  return data::InstallationResult(data::ResultCode::Numeric::kOk, "package installation successfully finalized");
96 }
97 
98 std::string AndroidManager::GetOTAPackageFilePath(const std::string& hash) {
99  fs::directory_iterator entryItEnd, entryIt{fs::path(data_ota_package_dir_)};
100  for (; entryIt != entryItEnd; ++entryIt) {
101  auto& entry_path = entryIt->path();
102  if (boost::filesystem::is_directory(*entryIt)) {
103  continue;
104  }
105  auto ext = entry_path.extension().string();
106  ext = ext.substr(1);
107  if (ext == hash) {
108  return entry_path.string();
109  }
110  }
111  return std::string{};
112 }
113 
114 bool AndroidManager::installationAborted(std::string* errorMessage) const {
115  std::string installation_log_file{"/cache/recovery/last_install"};
116  std::ifstream log(installation_log_file.c_str());
117  if (!log.good()) {
118  throw std::runtime_error(std::string("Error opening file ") + installation_log_file);
119  }
120  for (std::string line; std::getline(log, line);) {
121  if (boost::algorithm::find_first(line, "error:")) {
122  int error_code = std::stoi(line.substr(6));
123  if (error_code != 0) {
124  *errorMessage = std::string("Error code: ") + std::to_string(error_code);
125  return true;
126  }
127  }
128  }
129  return false;
130 }
AndroidManager
Definition: androidmanager.h:8
data::InstallationResult
Definition: types.h:182
Uptane::Target
Definition: tuf.h:210
data::ResultCode::Numeric::kInstallFailed
Package installation failed.