Merge develop into main (#343)
- Refactor `AppManifest`: add new fields and rename existing ones - Parse and validate the manifest from an app that is being installed. - Remove deprecated `scoped()` from `Lock` - Create `Tactility/Paths.h` - App loading at boot now properly parses the manifest files of external apps - Properly lock both source and destination locations during app install - Remove LVGL path variants from `AppPaths` and `ServicePaths` - Removed `xPath` base classes for apps and services. There's now `AppPaths` and `ServicePaths`. - Renamed app and service paths: "data" and "system" paths are now "user data" and "assets"
This commit is contained in:
committed by
GitHub
parent
a4d15b2a1e
commit
bab3eb19bc
@@ -1,17 +1,19 @@
|
||||
#include "Tactility/service/ServiceInstance.h"
|
||||
#include "Tactility/service/ServiceInstancePaths.h"
|
||||
#include <Tactility/service/ServiceInstance.h>
|
||||
|
||||
#include <Tactility/service/ServiceManifest.h>
|
||||
#include <Tactility/service/ServicePaths.h>
|
||||
|
||||
namespace tt::service {
|
||||
|
||||
ServiceInstance::ServiceInstance(std::shared_ptr<const service::ServiceManifest> manifest) :
|
||||
ServiceInstance::ServiceInstance(std::shared_ptr<const ServiceManifest> manifest) :
|
||||
manifest(manifest),
|
||||
service(manifest->createService())
|
||||
{}
|
||||
|
||||
const service::ServiceManifest& ServiceInstance::getManifest() const { return *manifest; }
|
||||
const ServiceManifest& ServiceInstance::getManifest() const { return *manifest; }
|
||||
|
||||
std::unique_ptr<Paths> ServiceInstance::getPaths() const {
|
||||
return std::make_unique<ServiceInstancePaths>(manifest);
|
||||
std::unique_ptr<ServicePaths> ServiceInstance::getPaths() const {
|
||||
return std::make_unique<ServicePaths>(manifest);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
#include "Tactility/service/ServiceInstancePaths.h"
|
||||
|
||||
#include "Tactility/MountPoints.h"
|
||||
|
||||
#define LVGL_PATH_PREFIX std::string("A:/")
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#define PARTITION_PREFIX std::string("/")
|
||||
#else
|
||||
#define PARTITION_PREFIX std::string("")
|
||||
#endif
|
||||
|
||||
namespace tt::service {
|
||||
|
||||
std::string ServiceInstancePaths::getDataDirectory() const {
|
||||
return PARTITION_PREFIX + file::DATA_PARTITION_NAME + "/service/" + manifest->id;
|
||||
}
|
||||
|
||||
std::string ServiceInstancePaths::getDataDirectoryLvgl() const {
|
||||
return LVGL_PATH_PREFIX + file::DATA_PARTITION_NAME + "/service/" + manifest->id;
|
||||
}
|
||||
|
||||
std::string ServiceInstancePaths::getDataPath(const std::string& childPath) const {
|
||||
assert(!childPath.starts_with('/'));
|
||||
return PARTITION_PREFIX + file::DATA_PARTITION_NAME + "/service/" + manifest->id + '/' + childPath;
|
||||
}
|
||||
|
||||
std::string ServiceInstancePaths::getDataPathLvgl(const std::string& childPath) const {
|
||||
assert(!childPath.starts_with('/'));
|
||||
return LVGL_PATH_PREFIX + file::DATA_PARTITION_NAME + "/service/" + manifest->id + '/' + childPath;
|
||||
}
|
||||
|
||||
std::string ServiceInstancePaths::getSystemDirectory() const {
|
||||
return PARTITION_PREFIX + file::SYSTEM_PARTITION_NAME + "/service/" + manifest->id;
|
||||
}
|
||||
|
||||
std::string ServiceInstancePaths::getSystemDirectoryLvgl() const {
|
||||
return LVGL_PATH_PREFIX + file::SYSTEM_PARTITION_NAME + "/service/" + manifest->id;
|
||||
}
|
||||
|
||||
std::string ServiceInstancePaths::getSystemPath(const std::string& childPath) const {
|
||||
assert(!childPath.starts_with('/'));
|
||||
return PARTITION_PREFIX + file::SYSTEM_PARTITION_NAME + "/service/" + manifest->id + '/' + childPath;
|
||||
}
|
||||
|
||||
std::string ServiceInstancePaths::getSystemPathLvgl(const std::string& childPath) const {
|
||||
return LVGL_PATH_PREFIX + file::SYSTEM_PARTITION_NAME + "/service/" + manifest->id + '/' + childPath;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#include <Tactility/service/ServicePaths.h>
|
||||
|
||||
#include <Tactility/service/ServiceManifest.h>
|
||||
#include <Tactility/MountPoints.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <format>
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
constexpr auto PARTITION_PREFIX = std::string("/");
|
||||
#else
|
||||
constexpr auto PARTITION_PREFIX = std::string("");
|
||||
#endif
|
||||
|
||||
namespace tt::service {
|
||||
|
||||
std::string ServicePaths::getUserDataDirectory() const {
|
||||
return std::format("{}{}/service/{}", PARTITION_PREFIX, file::DATA_PARTITION_NAME, manifest->id);
|
||||
}
|
||||
|
||||
std::string ServicePaths::getUserDataPath(const std::string& childPath) const {
|
||||
assert(!childPath.starts_with('/'));
|
||||
return std::format("{}/{}", getUserDataDirectory(), childPath);
|
||||
}
|
||||
|
||||
std::string ServicePaths::getAssetsDirectory() const {
|
||||
return std::format("{}{}/service/{}/assets", PARTITION_PREFIX, file::SYSTEM_PARTITION_NAME, manifest->id);
|
||||
}
|
||||
|
||||
std::string ServicePaths::getAssetsPath(const std::string& childPath) const {
|
||||
assert(!childPath.starts_with('/'));
|
||||
return std::format("{}/{}", getAssetsDirectory(), childPath);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
#include <Tactility/app/App.h>
|
||||
#include <Tactility/app/AppRegistration.h>
|
||||
#include <Tactility/app/ElfApp.h>
|
||||
#include <Tactility/file/File.h>
|
||||
#include <Tactility/network/HttpdReq.h>
|
||||
#include <Tactility/network/Url.h>
|
||||
#include <Tactility/Paths.h>
|
||||
#include <Tactility/service/development/DevelopmentSettings.h>
|
||||
#include <Tactility/service/ServiceManifest.h>
|
||||
#include <Tactility/service/ServiceRegistration.h>
|
||||
@@ -247,7 +247,7 @@ esp_err_t DevelopmentService::handleAppInstall(httpd_req_t* request) {
|
||||
}
|
||||
content_left -= content_read;
|
||||
|
||||
const std::string tmp_path = app::getTempPath();
|
||||
const std::string tmp_path = getTempPath();
|
||||
auto lock = file::getLock(tmp_path)->asScopedLock();
|
||||
|
||||
lock.lock();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "Tactility/service/gps/GpsService.h"
|
||||
|
||||
#include "Tactility/file/ObjectFile.h"
|
||||
#include <Tactility/file/ObjectFile.h>
|
||||
#include <Tactility/service/gps/GpsService.h>
|
||||
#include <Tactility/service/ServicePaths.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <unistd.h>
|
||||
@@ -17,12 +17,12 @@ bool GpsService::getConfigurationFilePath(std::string& output) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file::findOrCreateDirectory(paths->getDataDirectory(), 0777)) {
|
||||
TT_LOG_E(TAG, "Failed to find or create path %s", paths->getDataDirectory().c_str());
|
||||
if (!file::findOrCreateDirectory(paths->getUserDataDirectory(), 0777)) {
|
||||
TT_LOG_E(TAG, "Failed to find or create path %s", paths->getUserDataDirectory().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
output = paths->getDataPath("config.bin");
|
||||
output = paths->getUserDataPath("config.bin");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#include "Tactility/service/gps/GpsService.h"
|
||||
#include "Tactility/service/ServiceManifest.h"
|
||||
#include "Tactility/service/ServiceRegistration.h"
|
||||
#include <Tactility/service/gps/GpsService.h>
|
||||
|
||||
#include <Tactility/Log.h>
|
||||
#include <Tactility/file/File.h>
|
||||
#include <Tactility/Log.h>
|
||||
#include <Tactility/service/ServicePaths.h>
|
||||
#include <Tactility/service/ServiceManifest.h>
|
||||
#include <Tactility/service/ServiceRegistration.h>
|
||||
|
||||
using tt::hal::gps::GpsDevice;
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ void GuiService::requestDraw() {
|
||||
void GuiService::showApp(std::shared_ptr<app::AppContext> app) {
|
||||
lock();
|
||||
if (!isStarted) {
|
||||
TT_LOG_W(TAG, "Failed to show app %s: GUI not started", app->getManifest().id.c_str());
|
||||
TT_LOG_W(TAG, "Failed to show app %s: GUI not started", app->getManifest().appId.c_str());
|
||||
} else {
|
||||
// Ensure previous app triggers onHide() logic
|
||||
if (appToRender != nullptr) {
|
||||
|
||||
@@ -103,7 +103,7 @@ void LoaderService::onStartAppMessage(const std::string& id, app::LaunchId launc
|
||||
auto previous_app = !appStack.empty() ? appStack.top() : nullptr;
|
||||
auto new_app = std::make_shared<app::AppInstance>(app_manifest, launchId, parameters);
|
||||
|
||||
new_app->mutableFlags().hideStatusbar = (app_manifest->flags & app::AppManifest::Flags::HideStatusBar);
|
||||
new_app->mutableFlags().hideStatusbar = (app_manifest->appFlags & app::AppManifest::Flags::HideStatusBar);
|
||||
|
||||
appStack.push(new_app);
|
||||
transitionAppToState(new_app, app::State::Initial);
|
||||
@@ -136,12 +136,12 @@ void LoaderService::onStopAppMessage(const std::string& id) {
|
||||
// Stop current app
|
||||
auto app_to_stop = appStack.top();
|
||||
|
||||
if (app_to_stop->getManifest().id != id) {
|
||||
TT_LOG_E(TAG, "Stop app: id mismatch (wanted %s but found %s on top of stack)", id.c_str(), app_to_stop->getManifest().id.c_str());
|
||||
if (app_to_stop->getManifest().appId != id) {
|
||||
TT_LOG_E(TAG, "Stop app: id mismatch (wanted %s but found %s on top of stack)", id.c_str(), app_to_stop->getManifest().appId.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (original_stack_size == 1 && app_to_stop->getManifest().name != "Boot") {
|
||||
if (original_stack_size == 1 && app_to_stop->getManifest().appName != "Boot") {
|
||||
TT_LOG_E(TAG, "Stop app: can't stop root app");
|
||||
return;
|
||||
}
|
||||
@@ -162,12 +162,12 @@ void LoaderService::onStopAppMessage(const std::string& id) {
|
||||
|
||||
// We only expect the app to be referenced within the current scope
|
||||
if (app_to_stop.use_count() > 1) {
|
||||
TT_LOG_W(TAG, "Memory leak: Stopped %s, but use count is %ld", app_to_stop->getManifest().id.c_str(), app_to_stop.use_count() - 1);
|
||||
TT_LOG_W(TAG, "Memory leak: Stopped %s, but use count is %ld", app_to_stop->getManifest().appId.c_str(), app_to_stop.use_count() - 1);
|
||||
}
|
||||
|
||||
// Refcount is expected to be 2: 1 within app_to_stop and 1 within the current scope
|
||||
if (app_to_stop->getApp().use_count() > 2) {
|
||||
TT_LOG_W(TAG, "Memory leak: Stopped %s, but use count is %ld", app_to_stop->getManifest().id.c_str(), app_to_stop->getApp().use_count() - 2);
|
||||
TT_LOG_W(TAG, "Memory leak: Stopped %s, but use count is %ld", app_to_stop->getManifest().appId.c_str(), app_to_stop->getApp().use_count() - 2);
|
||||
}
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
@@ -224,7 +224,7 @@ void LoaderService::transitionAppToState(const std::shared_ptr<app::AppInstance>
|
||||
TT_LOG_I(
|
||||
TAG,
|
||||
"App \"%s\" state: %s -> %s",
|
||||
app_manifest.id.c_str(),
|
||||
app_manifest.appId.c_str(),
|
||||
appStateToString(old_state),
|
||||
appStateToString(state)
|
||||
);
|
||||
@@ -263,7 +263,7 @@ app::LaunchId LoaderService::startApp(const std::string& id, std::shared_ptr<con
|
||||
|
||||
void LoaderService::stopApp() {
|
||||
TT_LOG_I(TAG, "stopApp()");
|
||||
auto id = getCurrentAppContext()->getManifest().id;
|
||||
auto id = getCurrentAppContext()->getManifest().appId;
|
||||
dispatcherThread->dispatch([this, id]() {
|
||||
onStopAppMessage(id);
|
||||
});
|
||||
|
||||
@@ -84,10 +84,10 @@ void ScreenshotTask::taskMain() {
|
||||
auto appContext = app::getCurrentAppContext();
|
||||
if (appContext != nullptr) {
|
||||
const app::AppManifest& manifest = appContext->getManifest();
|
||||
if (manifest.id != last_app_id) {
|
||||
if (manifest.appId != last_app_id) {
|
||||
kernel::delayMillis(100);
|
||||
last_app_id = manifest.id;
|
||||
auto filename = std::format("{}/screenshot-{}.png", work.path, manifest.id);
|
||||
last_app_id = manifest.appId;
|
||||
auto filename = std::format("{}/screenshot-{}.png", work.path, manifest.appId);
|
||||
makeScreenshot(filename);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#include <Tactility/lvgl/Statusbar.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
|
||||
#include <Tactility/hal/power/PowerDevice.h>
|
||||
#include <Tactility/hal/sdcard/SdCardDevice.h>
|
||||
#include <Tactility/lvgl/Lvgl.h>
|
||||
#include <Tactility/service/gps/GpsService.h>
|
||||
#include <Tactility/lvgl/LvglSync.h>
|
||||
#include <Tactility/Mutex.h>
|
||||
#include <Tactility/Tactility.h>
|
||||
#include <Tactility/Timer.h>
|
||||
#include <Tactility/service/gps/GpsService.h>
|
||||
#include <Tactility/service/ServiceContext.h>
|
||||
#include <Tactility/service/ServicePaths.h>
|
||||
#include <Tactility/service/ServiceRegistration.h>
|
||||
#include <Tactility/service/wifi/Wifi.h>
|
||||
#include <Tactility/Timer.h>
|
||||
|
||||
namespace tt::service::statusbar {
|
||||
|
||||
@@ -148,7 +148,7 @@ class StatusbarService final : public Service {
|
||||
int8_t power_icon_id;
|
||||
const char* power_last_icon = nullptr;
|
||||
|
||||
std::unique_ptr<Paths> paths;
|
||||
std::unique_ptr<ServicePaths> paths;
|
||||
|
||||
void lock() const {
|
||||
mutex.lock();
|
||||
@@ -163,7 +163,7 @@ class StatusbarService final : public Service {
|
||||
bool show_icon = (gps_state == gps::State::OnPending) || (gps_state == gps::State::On);
|
||||
if (gps_last_state != show_icon) {
|
||||
if (show_icon) {
|
||||
auto icon_path = paths->getSystemPathLvgl(STATUSBAR_ICON_GPS);
|
||||
auto icon_path = "A:" + paths->getAssetsPath(STATUSBAR_ICON_GPS);
|
||||
lvgl::statusbar_icon_set_image(gps_icon_id, icon_path);
|
||||
lvgl::statusbar_icon_set_visibility(gps_icon_id, true);
|
||||
} else {
|
||||
@@ -179,7 +179,7 @@ class StatusbarService final : public Service {
|
||||
const char* desired_icon = getWifiStatusIcon(radio_state, is_secure);
|
||||
if (wifi_last_icon != desired_icon) {
|
||||
if (desired_icon != nullptr) {
|
||||
auto icon_path = paths->getSystemPathLvgl(desired_icon);
|
||||
auto icon_path = "A:" + paths->getAssetsPath(desired_icon);
|
||||
lvgl::statusbar_icon_set_image(wifi_icon_id, icon_path);
|
||||
lvgl::statusbar_icon_set_visibility(wifi_icon_id, true);
|
||||
} else {
|
||||
@@ -193,7 +193,7 @@ class StatusbarService final : public Service {
|
||||
const char* desired_icon = getPowerStatusIcon();
|
||||
if (power_last_icon != desired_icon) {
|
||||
if (desired_icon != nullptr) {
|
||||
auto icon_path = paths->getSystemPathLvgl(desired_icon);
|
||||
auto icon_path = "A:" + paths->getAssetsPath(desired_icon);
|
||||
lvgl::statusbar_icon_set_image(power_icon_id, icon_path);
|
||||
lvgl::statusbar_icon_set_visibility(power_icon_id, true);
|
||||
} else {
|
||||
@@ -212,7 +212,7 @@ class StatusbarService final : public Service {
|
||||
if (state != hal::sdcard::SdCardDevice::State::Timeout) {
|
||||
auto* desired_icon = getSdCardStatusIcon(state);
|
||||
if (sdcard_last_icon != desired_icon) {
|
||||
auto icon_path = paths->getSystemPathLvgl(desired_icon);
|
||||
auto icon_path = "A:" + paths->getAssetsPath(desired_icon);
|
||||
lvgl::statusbar_icon_set_image(sdcard_icon_id, icon_path);
|
||||
lvgl::statusbar_icon_set_visibility(sdcard_icon_id, true);
|
||||
sdcard_last_icon = desired_icon;
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
#include "Tactility/service/wifi/Wifi.h"
|
||||
|
||||
#ifndef ESP_PLATFORM
|
||||
|
||||
#include "Tactility/service/ServiceContext.h"
|
||||
#include <Tactility/service/wifi/Wifi.h>
|
||||
|
||||
#include <Tactility/Check.h>
|
||||
#include <Tactility/Log.h>
|
||||
#include <Tactility/Mutex.h>
|
||||
#include <Tactility/PubSub.h>
|
||||
#include <Tactility/service/Service.h>
|
||||
#include <Tactility/service/ServiceManifest.h>
|
||||
|
||||
namespace tt::service::wifi {
|
||||
|
||||
#define TAG "wifi"
|
||||
#define WIFI_CONNECTED_BIT BIT0
|
||||
#define WIFI_FAIL_BIT BIT1
|
||||
constexpr auto* TAG = "Wifi";
|
||||
|
||||
struct Wifi {
|
||||
Wifi() = default;
|
||||
~Wifi() = default;
|
||||
|
||||
/** @brief Locking mechanism for modifying the Wifi instance */
|
||||
Mutex mutex = Mutex(Mutex::Type::Recursive);
|
||||
/** @brief The public event bus */
|
||||
@@ -144,13 +139,13 @@ class WifiService final : public Service {
|
||||
|
||||
public:
|
||||
|
||||
bool onStart(TT_UNUSED ServiceContext& service) final {
|
||||
bool onStart(TT_UNUSED ServiceContext& service) override {
|
||||
tt_check(wifi == nullptr);
|
||||
wifi = new Wifi();
|
||||
return true;
|
||||
}
|
||||
|
||||
void onStop(TT_UNUSED ServiceContext& service) final {
|
||||
void onStop(TT_UNUSED ServiceContext& service) override {
|
||||
tt_check(wifi != nullptr);
|
||||
delete wifi;
|
||||
wifi = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user