Skip to content

Commit

Permalink
Refactor services into classes
Browse files Browse the repository at this point in the history
  • Loading branch information
KenVanHoeylandt committed Jan 23, 2025
1 parent bb7e798 commit 0936ce1
Show file tree
Hide file tree
Showing 20 changed files with 276 additions and 246 deletions.
6 changes: 0 additions & 6 deletions Tactility/Private/app/AppInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,6 @@ class AppInstance : public AppContext {
* Do not mutate after app creation.
*/
std::shared_ptr<const tt::Bundle> _Nullable parameters;
/** @brief @brief Contextual data related to the running app's instance
* The app can attach its data to this.
* The lifecycle is determined by the on_start and on_stop methods in the AppManifest.
* These manifest methods can optionally allocate/free data that is attached here.
*/
std::shared_ptr<void> _Nullable data;

std::shared_ptr<App> app;

Expand Down
26 changes: 9 additions & 17 deletions Tactility/Source/Tactility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,6 @@ namespace service {
#endif
}

static const std::vector<const service::ServiceManifest*> system_services = {
&service::loader::manifest,
&service::gui::manifest, // depends on loader service
&service::statusbar::manifest,
#if TT_FEATURE_SCREENSHOT_ENABLED
&service::screenshot::manifest
#endif
};

// endregion

// region Default apps
Expand Down Expand Up @@ -125,18 +116,19 @@ static void register_user_apps(const std::vector<const app::AppManifest*>& apps)

static void register_and_start_system_services() {
TT_LOG_I(TAG, "Registering and starting system services");
for (const auto& service_manifest: system_services) {
addService(service_manifest);
tt_check(service::startService(service_manifest->id));
}
addService(service::loader::manifest);
addService(service::gui::manifest);
addService(service::statusbar::manifest);
#if TT_FEATURE_SCREENSHOT_ENABLED
addService(service::screenshot::manifest);
#endif
}

static void register_and_start_user_services(const std::vector<const service::ServiceManifest*>& services) {
static void register_and_start_user_services(const std::vector<const service::ServiceManifest*>& manifests) {
TT_LOG_I(TAG, "Registering and starting user services");
for (auto* manifest : services) {
for (auto* manifest : manifests) {
assert(manifest != nullptr);
addService(manifest);
tt_check(service::startService(manifest->id));
addService(*manifest);
}
}

Expand Down
38 changes: 22 additions & 16 deletions Tactility/Source/service/gui/Gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,30 +142,36 @@ static int32_t guiMain(TT_UNUSED void* p) {

// region AppManifest

static void start(TT_UNUSED ServiceContext& service) {
gui = gui_alloc();
class GuiService : public Service {

gui->thread->setPriority(THREAD_PRIORITY_SERVICE);
gui->thread->start();
}
public:

static void stop(TT_UNUSED ServiceContext& service) {
lock();
void onStart(TT_UNUSED ServiceContext& service) override {
tt_assert(gui == nullptr);
gui = gui_alloc();

ThreadId thread_id = gui->thread->getId();
thread_flags_set(thread_id, GUI_THREAD_FLAG_EXIT);
gui->thread->join();
delete gui->thread;
gui->thread->setPriority(THREAD_PRIORITY_SERVICE);
gui->thread->start();
}

unlock();
void onStop(TT_UNUSED ServiceContext& service) override {
tt_assert(gui != nullptr);
lock();

gui_free(gui);
}
ThreadId thread_id = gui->thread->getId();
thread_flags_set(thread_id, GUI_THREAD_FLAG_EXIT);
gui->thread->join();
delete gui->thread;

unlock();

gui_free(gui);
}
};

extern const ServiceManifest manifest = {
.id = "Gui",
.onStart = &start,
.onStop = &stop
.createService = create<GuiService>
};

// endregion
Expand Down
38 changes: 21 additions & 17 deletions Tactility/Source/service/loader/Loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,31 +295,35 @@ static void stopAppInternal() {

// region AppManifest

static void loader_start(TT_UNUSED ServiceContext& service) {
tt_check(loader_singleton == nullptr);
loader_singleton = loader_alloc();
loader_singleton->dispatcherThread->start();
}
class LoaderService : public Service {

static void loader_stop(TT_UNUSED ServiceContext& service) {
tt_check(loader_singleton != nullptr);
public:

// Send stop signal to thread and wait for thread to finish
if (!loader_singleton->mutex.lock(2000 / portTICK_PERIOD_MS)) {
TT_LOG_W(TAG, LOG_MESSAGE_MUTEX_LOCK_FAILED_FMT, "loader_stop");
void onStart(TT_UNUSED ServiceContext& service) override {
tt_check(loader_singleton == nullptr);
loader_singleton = loader_alloc();
loader_singleton->dispatcherThread->start();
}
loader_singleton->dispatcherThread->stop();

loader_singleton->mutex.unlock();
void onStop(TT_UNUSED ServiceContext& service) override {
tt_check(loader_singleton != nullptr);

loader_free();
loader_singleton = nullptr;
}
// Send stop signal to thread and wait for thread to finish
if (!loader_singleton->mutex.lock(2000 / portTICK_PERIOD_MS)) {
TT_LOG_W(TAG, LOG_MESSAGE_MUTEX_LOCK_FAILED_FMT, "loader_stop");
}
loader_singleton->dispatcherThread->stop();

loader_singleton->mutex.unlock();

loader_free();
loader_singleton = nullptr;
}
};

extern const ServiceManifest manifest = {
.id = "Loader",
.onStart = &loader_start,
.onStop = &loader_stop
.createService = create<LoaderService>
};

// endregion
Expand Down
14 changes: 2 additions & 12 deletions Tactility/Source/service/screenshot/Screenshot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,7 @@ namespace tt::service::screenshot {
extern const ServiceManifest manifest;

std::shared_ptr<ScreenshotService> _Nullable optScreenshotService() {
ServiceContext* context = service::findServiceById(manifest.id);
if (context != nullptr) {
return std::static_pointer_cast<ScreenshotService>(context->getData());
} else {
return nullptr;
}
return service::findServiceById<ScreenshotService>(manifest.id);
}

void ScreenshotService::startApps(const char* path) {
Expand Down Expand Up @@ -89,14 +84,9 @@ bool ScreenshotService::isTaskStarted() {
}
}

static void onStart(ServiceContext& serviceContext) {
auto service = std::make_shared<ScreenshotService>();
serviceContext.setData(service);
}

extern const ServiceManifest manifest = {
.id = "Screenshot",
.onStart = onStart
.createService = create<ScreenshotService>
};

} // namespace
Expand Down
7 changes: 4 additions & 3 deletions Tactility/Source/service/screenshot/Screenshot.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#pragma once

#include "Mutex.h"
#include "ScreenshotTask.h"
#include "TactilityConfig.h"

#if TT_FEATURE_SCREENSHOT_ENABLED

#include "Mutex.h"
#include "ScreenshotTask.h"
#include "service/Service.h"
#include <cstdint>

namespace tt::service::screenshot {
Expand All @@ -16,7 +17,7 @@ enum class Mode {
Apps
};

class ScreenshotService {
class ScreenshotService : public Service {

private:

Expand Down
46 changes: 22 additions & 24 deletions Tactility/Source/service/statusbar/Statusbar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,38 +223,36 @@ static void onUpdate(std::shared_ptr<void> parameter) {
updatePowerStatusIcon(paths, data);
}

static void onStart(ServiceContext& service) {
lvgl::lock(TtWaitForever);
auto data = std::make_shared<ServiceData>();
lvgl::unlock();
class StatusbarService : public Service {

data->paths = service.getPaths();
std::shared_ptr<ServiceData> data = std::make_shared<ServiceData>();

service.setData(data);
public:

// TODO: Make thread-safe for LVGL
lvgl::statusbar_icon_set_visibility(data->wifi_icon_id, true);
updateWifiIcon(data->paths.get(), data);
updateSdCardIcon(data->paths.get(), data); // also updates visibility
updatePowerStatusIcon(data->paths.get(), data);

data->updateTimer = std::make_unique<Timer>(Timer::Type::Periodic, onUpdate, data);
// We want to try and scan more often in case of startup or scan lock failure
data->updateTimer->start(1000);
}
void onStart(ServiceContext& service) override {
data->paths = service.getPaths();

static void onStop(ServiceContext& service) {
auto data = std::static_pointer_cast<ServiceData>(service.getData());
// TODO: Make thread-safe for LVGL
lvgl::statusbar_icon_set_visibility(data->wifi_icon_id, true);
updateWifiIcon(data->paths.get(), data);
updateSdCardIcon(data->paths.get(), data); // also updates visibility
updatePowerStatusIcon(data->paths.get(), data);

data->updateTimer = std::make_unique<Timer>(Timer::Type::Periodic, onUpdate, data);
// We want to try and scan more often in case of startup or scan lock failure
data->updateTimer->start(1000);
}

void onStop(ServiceContext& service) override{
data->updateTimer->stop();
data->updateTimer = nullptr;
}
};

// Stop thread
data->updateTimer->stop();
data->updateTimer = nullptr;
}

extern const ServiceManifest manifest = {
.id = "Statusbar",
.onStart = onStart,
.onStop = onStop
.createService = create<StatusbarService>
};

// endregion service
Expand Down
13 changes: 8 additions & 5 deletions TactilityHeadless/Private/service/ServiceInstance.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "service/ServiceContext.h"
#include "service/Service.h"

namespace tt::service {

Expand All @@ -9,19 +10,21 @@ class ServiceInstance : public ServiceContext {
private:

Mutex mutex = Mutex(Mutex::Type::Normal);
const service::ServiceManifest& manifest;
std::shared_ptr<void> data = nullptr;
std::shared_ptr<const ServiceManifest> manifest;
std::shared_ptr<Service> service;

public:

explicit ServiceInstance(const service::ServiceManifest& manifest);
explicit ServiceInstance(std::shared_ptr<const service::ServiceManifest> manifest);
~ServiceInstance() override = default;

/** @return a reference ot the service's manifest */
const service::ServiceManifest& getManifest() const override;
std::shared_ptr<void> getData() const override;
void setData(std::shared_ptr<void> newData) override;

/** Retrieve the paths that are relevant to this service */
std::unique_ptr<Paths> getPaths() const override;

std::shared_ptr<Service> getService() const { return service; }
};

}
4 changes: 2 additions & 2 deletions TactilityHeadless/Private/service/ServiceInstancePaths.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ class ServiceInstancePaths final : public Paths {

private:

const ServiceManifest& manifest;
std::shared_ptr<const ServiceManifest> manifest;

public:

explicit ServiceInstancePaths(const ServiceManifest& manifest) : manifest(manifest) {}
explicit ServiceInstancePaths(std::shared_ptr<const ServiceManifest> manifest) : manifest(std::move(manifest)) {}
~ServiceInstancePaths() final = default;

std::string getDataDirectory() const final;
Expand Down
12 changes: 2 additions & 10 deletions TactilityHeadless/Source/TactilityHeadless.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,12 @@ namespace service::sdcard { extern const ServiceManifest manifest; }

static Dispatcher mainDispatcher;

static const service::ServiceManifest* const system_services[] = {
&service::sdcard::manifest,
&service::wifi::manifest
};

static const hal::Configuration* hardwareConfig = nullptr;

static void register_and_start_system_services() {
TT_LOG_I(TAG, "Registering and starting system services");
int app_count = sizeof(system_services) / sizeof(service::ServiceManifest*);
for (int i = 0; i < app_count; ++i) {
addService(system_services[i]);
tt_check(service::startService(system_services[i]->id));
}
addService(service::sdcard::manifest);
addService(service::wifi::manifest);
}

void initHeadless(const hal::Configuration& config) {
Expand Down
24 changes: 24 additions & 0 deletions TactilityHeadless/Source/service/Service.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#pragma once

#include <memory>

namespace tt::service {

// Forward declaration
class ServiceContext;

class Service {

public:

Service() = default;
virtual ~Service() = default;

virtual void onStart(ServiceContext& serviceContext) {}
virtual void onStop(ServiceContext& serviceContext) {}
};

template<typename T>
std::shared_ptr<Service> create() { return std::shared_ptr<T>(new T); }

}
5 changes: 1 addition & 4 deletions TactilityHeadless/Source/service/ServiceContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ class ServiceContext {

/** @return a reference ot the service's manifest */
virtual const service::ServiceManifest& getManifest() const = 0;
/** @return a shared pointer to the data that is attached to the service */
virtual std::shared_ptr<void> _Nullable getData() const = 0;
/** Set the data for a service. */
virtual void setData(std::shared_ptr<void> newData) = 0;

/** Retrieve the paths that are relevant to this service */
virtual std::unique_ptr<Paths> getPaths() const = 0;
};
Expand Down
Loading

0 comments on commit 0936ce1

Please sign in to comment.