Skip to content
This repository has been archived by the owner on May 21, 2024. It is now read-only.

Commit

Permalink
Android support
Browse files Browse the repository at this point in the history
* build script update required by atkualizr-android
* package manager for android
* log system integration
  • Loading branch information
riqkum committed Dec 14, 2018
1 parent 16b3ecb commit caa76bf
Show file tree
Hide file tree
Showing 14 changed files with 289 additions and 15 deletions.
24 changes: 21 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
message(FATAL_ERROR "Aktualizr does not support building in the source tree. Please remove CMakeCache.txt and the CMakeFiles/ directory, then create a subdirectory to build in: mkdir build; cd build; cmake ..")
endif()

set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake-modules)
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake-modules;${PROJECT_SOURCE_DIR}/aktualizr/cmake-modules")
configure_file(CTestCustom.cmake CTestCustom.cmake)

unset(AKTUALIZR_CHECKED_SRCS CACHE)
Expand All @@ -47,6 +47,15 @@ unset(AKTUALIZR_CHECKED_SRCS CACHE)
set(Boost_USE_STATIC_LIBS ON)
set(BOOST_COMPONENTS log_setup log filesystem program_options)

if(ANDROID)
set(BOOST_ROOT ${PREBUILD_BOOST_ROOT})
set(Boost_INCLUDE_DIR ${BOOST_ROOT}/include)
set(Boost_LIBRARY_DIR ${BOOST_ROOT}/libs/llvm/${ANDROID_ABI})
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
endif()
endif(ANDROID)

if(BUILD_OPCUA)
list(APPEND BOOST_COMPONENTS serialization iostreams)
endif(BUILD_OPCUA)
Expand All @@ -71,6 +80,7 @@ find_package(sodium REQUIRED)
find_package(SQLite3 REQUIRED)
find_package(Git)
find_package(Asn1c REQUIRED)
find_package(ZLIB)

if(NOT AKTUALIZR_VERSION)
if(GIT_EXECUTABLE)
Expand Down Expand Up @@ -260,6 +270,7 @@ include_directories(${SQLITE3_INCLUDE_DIRS})
include_directories(${LIBP11_INCLUDE_DIR})
include_directories(${sodium_INCLUDE_DIR})
include_directories(${OPENSSL_INCLUDE_DIR})
include_directories(${CURL_INCLUDE_DIR})
include_directories(${LibArchive_INCLUDE_DIR})

set_source_files_properties(third_party/jsoncpp/jsoncpp.cpp PROPERTIES COMPILE_FLAGS -w)
Expand All @@ -279,6 +290,9 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")

if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL "4.9" OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "4.9")
add_definitions(-Wshadow)
if (CMAKE_SYSTEM_NAME MATCHES "Android")
add_definitions(-Wno-sign-conversion)
endif ()
endif ()

if (WARNING_AS_ERROR)
Expand Down Expand Up @@ -330,7 +344,12 @@ set (AKTUALIZR_EXTERNAL_LIBS
${LIBP11_LIBRARIES}
${LIBDPKG_LIBRARIES}
${GLIB2_LIBRARIES}
${SYSTEMD_LIBRARY})
${SYSTEMD_LIBRARY}
${ZLIB_LIBRARY})

if(ANDROID)
list(APPEND AKTUALIZR_EXTERNAL_LIBS liblog.so)
endif()

get_directory_property(hasParent PARENT_DIRECTORY)
if(hasParent)
Expand All @@ -345,7 +364,6 @@ if(BUILD_WITH_CODE_COVERAGE)
list(APPEND TEST_LIBS gcov)
endif(BUILD_WITH_CODE_COVERAGE)


include(CTest)
ENABLE_TESTING()
# It would be great to use GTEST_OUTPUT directly, but I couldn't get it to work.
Expand Down
15 changes: 12 additions & 3 deletions src/libaktualizr/config/config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,7 @@ KeyManagerConfig Config::keymanagerConfig() const {
void Config::postUpdateValues() {
logger_set_threshold(logger);

if (provision.provision_path.empty()) {
provision.mode = ProvisionMode::kImplicit;
}
provision.mode = provision.provision_path.empty() ? ProvisionMode::kImplicit : ProvisionMode::kAutomatic;

if (tls.server.empty()) {
if (!tls.server_url_path.empty()) {
Expand Down Expand Up @@ -258,10 +256,21 @@ void Config::readSecondaryConfigs(const boost::filesystem::path& sconfigs_dir) {
LOG_ERROR << "Could not read secondary configs from " << sconfigs_dir << ": not a directory";
return;
}
#if (!defined(ANDROID) || __ANDROID_API__ >= 28)
for (const auto& config_file : Utils::glob((sconfigs_dir / "*.json").string())) {
LOG_INFO << "Parsing secondary config: " << config_file;
uptane.secondary_configs.emplace_back(config_file);
}
#else
boost::filesystem::directory_iterator entryItEnd, entryIt(sconfigs_dir);
for (; entryIt != entryItEnd; ++entryIt) {
auto& config_file = entryIt->path();
if (!boost::filesystem::is_directory(*entryIt) && config_file.extension().string() == ".json") {
LOG_INFO << "Parsing secondary config: " << config_file;
uptane.secondary_configs.emplace_back(config_file);
}
}
#endif
}

void Config::writeToStream(std::ostream& sink) const {
Expand Down
31 changes: 31 additions & 0 deletions src/libaktualizr/logging/boost_logging.cc
Original file line number Diff line number Diff line change
@@ -1,11 +1,36 @@
#include "logging.h"
#include "utilities/config_utils.h"

#if (defined(ANDROID) && defined(__clang__))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
#pragma GCC diagnostic ignored "-Wsign-conversion"
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wshorten-64-to-32"
#include <android/log.h>
#include <boost/log/utility/setup/console.hpp>
#pragma GCC diagnostic pop
#else
#include <boost/log/utility/setup/console.hpp>
#endif

namespace logging = boost::log;
using boost::log::trivial::severity_level;

#if defined(ANDROID)
class android_log_sink : public logging::sinks::basic_sink_backend<logging::sinks::synchronized_feeding> {
public:
explicit android_log_sink() {}

void consume(logging::record_view const& rec) {
const auto& rec_message_attr = rec[logging::aux::default_attribute_names::message()];
int log_priority = android_LogPriority::ANDROID_LOG_VERBOSE +
rec[logging::aux::default_attribute_names::severity()].extract_or_default(0);
__android_log_write(log_priority, "aktualizr", rec_message_attr.extract_or_default(std::string("N/A")).c_str());
}
};
#endif // defined(ANDROID)

static severity_level gLoggingThreshold;

void LoggerConfig::updateFromPropertyTree(const boost::property_tree::ptree& pt) {
Expand All @@ -18,8 +43,14 @@ int64_t get_curlopt_verbose() { return gLoggingThreshold <= boost::log::trivial:

void logger_init() {
gLoggingThreshold = boost::log::trivial::info;

#if defined(ANDROID)
typedef logging::sinks::synchronous_sink<android_log_sink> sink_t;
logging::core::get()->add_sink(boost::shared_ptr<sink_t>(new sink_t()));
#else
logging::add_console_log(std::cout, boost::log::keywords::format = "%Message%",
boost::log::keywords::auto_flush = true);
#endif
boost::log::core::get()->set_filter(boost::log::trivial::severity >= gLoggingThreshold);
}

Expand Down
9 changes: 9 additions & 0 deletions src/libaktualizr/logging/logging.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
#ifndef SOTA_CLIENT_TOOLS_LOGGING_H_
#define SOTA_CLIENT_TOOLS_LOGGING_H_

#if (defined(ANDROID) && defined(__clang__))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
#pragma GCC diagnostic ignored "-Wsign-conversion"
#pragma GCC diagnostic ignored "-Wshorten-64-to-32"
#include <boost/log/trivial.hpp>
#pragma GCC diagnostic pop
#else
#include <boost/log/trivial.hpp>
#endif

#include "logging_config.h"

Expand Down
6 changes: 6 additions & 0 deletions src/libaktualizr/package_manager/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,9 @@ aktualizr_source_file_checks(packagemanagerfactory_test.cc ostreemanager_test.cc

aktualizr_source_file_checks(ostreemanager.cc ostreereposync.cc
ostreemanager.h ostreereposync.h)

if(ANDROID)
target_sources(package_manager PRIVATE androidmanager.cc)
endif(ANDROID)

aktualizr_source_file_checks(androidmanager.cc androidmanager.h)
102 changes: 102 additions & 0 deletions src/libaktualizr/package_manager/androidmanager.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#include "androidmanager.h"

#include "utilities/utils.h"

Json::Value AndroidManager::getInstalledPackages() const {
Json::Value packages(Json::arrayValue);
Json::Value package;
package["name"] = "aktualizr";
package["version"] = "n/a";
packages.append(package);
return packages;
}

Uptane::Target AndroidManager::getCurrent() const {
std::vector<Uptane::Target> installed_versions;
std::string current_hash;
size_t current_k = SIZE_MAX;
storage_->loadPrimaryInstalledVersions(&installed_versions, &current_k, nullptr);
if (current_k != SIZE_MAX) {
current_hash = installed_versions[current_k].sha256Hash();
}
AndroidInstallationState installation_state;
if (AndroidInstallationDispatcher::GetState().state_ == AndroidInstallationState::STATE_INSTALLED) {
installation_state = AndroidInstallationDispatcher::Dispatch();
if (installation_state.state_ == AndroidInstallationState::STATE_UPDATE) {
current_hash = installation_state.payload_;
}
}
std::vector<Uptane::Target>::iterator it;
for (it = installed_versions.begin(); it != installed_versions.end(); it++) {
if (it->sha256Hash() == current_hash) {
if (installation_state.state_ == AndroidInstallationState::STATE_UPDATE) {
storage_->savePrimaryInstalledVersion(*it, InstalledVersionUpdateMode::kCurrent);
auto outcome = data::InstallOutcome(data::UpdateResultCode::kOk, "package successfully intalled");
storage_->storeInstallationResult(data::OperationResult(it->filename(), outcome));
}
return *it;
}
}
return getUnknown();
}

data::InstallOutcome AndroidManager::install(const Uptane::Target& target) const {
if (AndroidInstallationDispatcher::GetState().state_ == AndroidInstallationState::STATE_NOP) {
LOG_INFO << "Begin Android package installation";
storage_->savePrimaryInstalledVersion(target, InstalledVersionUpdateMode::kPending);
auto package_filename = (Utils::getStorageRootPath() / target.filename()).string() + "." + target.sha256Hash();
std::ofstream package_file(package_filename.c_str());
if (!package_file.good()) {
throw std::runtime_error(std::string("Error opening file ") + package_filename);
}
package_file << *storage_->openTargetFile(target);
AndroidInstallationDispatcher::Dispatch(package_filename);
}
return data::InstallOutcome(data::UpdateResultCode::kInProgress, "Installation is in progress");
}

AndroidInstallationState AndroidInstallationDispatcher::GetState() {
boost::filesystem::directory_iterator entryItEnd, entryIt(Utils::getStorageRootPath());
for (; entryIt != entryItEnd; ++entryIt) {
auto& entry_path = entryIt->path();
if (boost::filesystem::is_directory(*entryIt)) {
continue;
}
auto package_file_path = entry_path.string();
auto ext = entry_path.extension().string();
if (ext == ".installed") {
return {AndroidInstallationState::STATE_INSTALLED, package_file_path};
} else if (ext == ".inprogress") {
return {AndroidInstallationState::STATE_IN_PROGRESS, package_file_path};
} else if (true /* check ext is actually a hash */) {
return {AndroidInstallationState::STATE_READY, package_file_path};
}
}
return {AndroidInstallationState::STATE_NOP, ""};
}

AndroidInstallationState AndroidInstallationDispatcher::Dispatch() {
auto current = GetState();
if (current.state_ == AndroidInstallationState::STATE_INSTALLED) {
auto hash = boost::filesystem::path(current.payload_).stem().extension().string();
if (!hash.empty()) {
hash = hash.substr(1);
}
boost::filesystem::remove(current.payload_);
return {AndroidInstallationState::STATE_UPDATE, hash};
} else if (current.state_ == AndroidInstallationState::STATE_IN_PROGRESS) {
boost::filesystem::path installed_package_file_path(current.payload_);
installed_package_file_path.replace_extension(".installed");
boost::filesystem::rename(boost::filesystem::path(current.payload_), installed_package_file_path);
return {AndroidInstallationState::STATE_UPDATE, installed_package_file_path.string()};
} else if (true /* check ext is actually a hash */) {
boost::filesystem::path inprogress_package_file_path = boost::filesystem::path(current.payload_ + ".inprogress");
boost::filesystem::rename(boost::filesystem::path(current.payload_), inprogress_package_file_path);
return {AndroidInstallationState::STATE_IN_PROGRESS, inprogress_package_file_path.string()};
}
return {AndroidInstallationState::STATE_NOP, ""};
}

AndroidInstallationState AndroidInstallationDispatcher::Dispatch(const std::string& package_filename) {
return {AndroidInstallationState::STATE_READY, package_filename};
}
43 changes: 43 additions & 0 deletions src/libaktualizr/package_manager/androidmanager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#ifndef ANDROIDMANAGER_H
#define ANDROIDMANAGER_H

#include "package_manager/packagemanagerinterface.h"
#include "storage/invstorage.h"

class AndroidInstallationDispatcher;

class AndroidManager : public PackageManagerInterface {
public:
explicit AndroidManager(std::shared_ptr<INvStorage> storage) : storage_(std::move(storage)) {}
~AndroidManager() override = default;
std::string name() const override { return "android"; }
Json::Value getInstalledPackages() const override;

Uptane::Target getCurrent() const override;
bool imageUpdated() override { return true; };

data::InstallOutcome install(const Uptane::Target &target) const override;
data::InstallOutcome finalizeInstall(const Uptane::Target &target) const override {
(void)target;
throw std::runtime_error("Unimplemented");
}

private:
std::shared_ptr<INvStorage> storage_;
};

struct AndroidInstallationState {
enum State { STATE_NOP, STATE_READY, STATE_IN_PROGRESS, STATE_INSTALLED, STATE_UPDATE };

State state_;
std::string payload_;
};

class AndroidInstallationDispatcher {
public:
static AndroidInstallationState GetState();
static AndroidInstallationState Dispatch(); // get the current state automatically
static AndroidInstallationState Dispatch(const std::string &package_filename); // installation cycle entry point
};

#endif // ANDROIDMANAGER_H
4 changes: 3 additions & 1 deletion src/libaktualizr/package_manager/packagemanagerconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

#include "utilities/config_utils.h"

enum class PackageManager { kNone = 0, kOstree, kDebian };
enum class PackageManager { kNone = 0, kOstree, kDebian, kAndroid };

struct PackageConfig {
PackageManager type{PackageManager::kOstree};
Expand All @@ -33,6 +33,8 @@ inline void CopyFromConfig(PackageManager& dest, const std::string& option_name,
dest = PackageManager::kOstree;
} else if (pm_type == "debian") {
dest = PackageManager::kDebian;
} else if (pm_type == "android") {
dest = PackageManager::kAndroid;
} else {
dest = PackageManager::kNone;
}
Expand Down
10 changes: 10 additions & 0 deletions src/libaktualizr/package_manager/packagemanagerfactory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
#include "package_manager/debianmanager.h"
#endif

#if defined(ANDROID)
#include "package_manager/androidmanager.h"
#endif

#include "logging/logging.h"

std::shared_ptr<PackageManagerInterface> PackageManagerFactory::makePackageManager(
Expand All @@ -27,6 +31,12 @@ std::shared_ptr<PackageManagerInterface> PackageManagerFactory::makePackageManag
return std::make_shared<DebianManager>(pconfig, storage);
#else
throw std::runtime_error("aktualizr was compiled without debian packages support!");
#endif
case PackageManager::kAndroid:
#if defined(ANDROID)
return std::make_shared<AndroidManager>(storage);
#else
throw std::runtime_error("aktualizr was compiled without android support!");
#endif
case PackageManager::kNone:
return std::make_shared<PackageManagerFake>(pconfig, storage, bootloader);
Expand Down
4 changes: 1 addition & 3 deletions src/libaktualizr/telemetry/telemetryconfig.cc
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#include "telemetry/telemetryconfig.h"

#include <boost/log/trivial.hpp>

#include "utilities/config_utils.h"

void TelemetryConfig::updateFromPropertyTree(const boost::property_tree::ptree& pt) {
Expand All @@ -10,4 +8,4 @@ void TelemetryConfig::updateFromPropertyTree(const boost::property_tree::ptree&

void TelemetryConfig::writeToStream(std::ostream& out_stream) const {
writeOption(out_stream, report_network, "report_network");
}
}
2 changes: 2 additions & 0 deletions src/libaktualizr/uptane/managedsecondary.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include "logging/logging.h"
#include "utilities/events.h"

#include <sys/stat.h>

namespace Uptane {
ManagedSecondary::ManagedSecondary(const SecondaryConfig &sconfig_in) : SecondaryInterface(sconfig_in) {
// TODO: FIX
Expand Down
Loading

0 comments on commit caa76bf

Please sign in to comment.