Skip to content

Refactor app loading and window management - #609

Open
KenVanHoeylandt wants to merge 25 commits into
mainfrom
develop
Open

Refactor app loading and window management#609
KenVanHoeylandt wants to merge 25 commits into
mainfrom
develop

Conversation

@KenVanHoeylandt

@KenVanHoeylandt KenVanHoeylandt commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • Added application installation, metadata parsing, lifecycle management, event handling, runtime loading, and app data/asset paths.
    • Added an LVGL window manager and ESP32 application support.
    • Added polling system events plus typed bundles, preferences, and properties-file storage APIs.
  • Bug Fixes
    • Improved boot reliability through ESP32 PSRAM configuration updates.
    • Updated event handling across Wi-Fi, time, status bar, and device components.
  • Tests
    • Added comprehensive coverage for applications, events, windows, storage, and preferences.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This change adds application installation, metadata parsing, memory and ELF loading, task scheduling, lifecycle events, and manager APIs. It adds an LVGL window manager with stacked windows and state waiting. System events now support renamed callback APIs and caller-owned polling subscriptions. Build and SDK configuration now include the new modules and packaging paths. Tests cover application management, app events, and system-event behavior. ESP32 device settings disable selected PSRAM execution and data placement.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.98% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes to app loading and LVGL window management.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch develop

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 18

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

🟡 Minor comments (8)
Modules/lvgl-window-manager/source/window_manager.cpp-79-84 (1)

79-84: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Honor the window_manager_configure() lifecycle contract.

The header states that this call has no effect after startup. This implementation replaces s.screen_init while started. The replacement becomes observable after the next stop/start cycle.

Return without changing s.screen_init when the manager is started. Coordinate this with a starting lifecycle state so a concurrent start cannot bypass the pre-start requirement.

TactilityKernel/include/tactility/system_event.h-139-140 (1)

139-140: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Permit callers to read event output fields.

The warning prohibits reading timestamp, data, and data_len. These fields contain the result of system_event_await(). The tests also read data and data_len.

Document task, sequence, consumed_sequence, and next as internal. Permit reads of the event output fields after a successful await.

Modules/app-module/source/app_scheduler.cpp-119-164 (1)

119-164: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Use tskNO_AFFINITY for the app thread affinity.

thread_set_affinity(thread, affinity) stores the raw affinity value, so this passes -1 to xTaskCreatePinnedToCore on ESP-IDF instead of the port’s documented no-affinity value. Keep the -1 as the default/compatibility comment if needed, but pass tskNO_AFFINITY when creating the task.

Modules/app-module/source/event.cpp-96-114 (1)

96-114: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Route app event notifications to a reserved notification index.

Current usages include polling subscriptions, lvTask, libTask waiting tasks, and the USB host task. They call the same non-indexed notification APIs or ulTaskNotifyTake(pdTRUE, 0) and would have their notification credit cleared by app_event_await on a shared index 0 slot. Use xTaskNotifyGiveIndexed/ulTaskNotifyTakeIndexed or ulTaskNotifyTakeIndexed(pdFALSE, 0) with an app-only index.

Modules/app-module/source/app_install.cpp-237-238 (1)

237-238: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

The lock comment states the inverse of the real contract.

uninstall_locked() never takes install_registry().mutex. Both callers take it first: app_install() at line 329 and app_uninstall() at line 379. The _locked suffix also implies the caller holds the lock.

A future caller that follows this comment either deadlocks or mutates the registry unlocked.

📝 Proposed fix
-// Takes install_registry().mutex - caller must not already hold it.
+// Caller must already hold install_registry().mutex.
 error_t uninstall_locked(const std::string& app_id) {
Modules/app-module/include/app/manager.h-36-42 (1)

36-42: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the malformed sentence and widen the documented constraint.

Lines 38-39 read "Safe to call app_manager_add()/_remove() from within @a visitor is NOT guaranteed", which is not a grammatical sentence.

The constraint is also narrower than the implementation allows. app_manager_for_each_manifest() in manager.cpp runs visitor while it holds the ledger mutex. Any app_manager_* call from the visitor can deadlock, not only app_manager_add()/app_manager_remove().

📝 Proposed doc fix
- * Calls `@a` visitor once for every registered manifest (e.g. for AppList/Settings to enumerate
- * apps to show). Iteration order is unspecified. Safe to call app_manager_add()/_remove() from
- * within `@a` visitor is NOT guaranteed - do not mutate the registry from inside the callback.
+ * Calls `@a` visitor once for every registered manifest (e.g. for AppList/Settings to enumerate
+ * apps to show). Iteration order is unspecified.
+ * `@warning` `@a` visitor runs with app-module's internal registry lock held. Do not call any
+ * app_manager_*() function from inside `@a` visitor - copy out what you need and act on it after
+ * this call returns.
Modules/app-module/source/manager.cpp-124-126 (1)

124-126: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Use a kernel-provided tick conversion for the stop timeout.

app_scheduler_stop() expects TickType_t; TactilityKernel/include/tactility/freertos/task.h defines FreeRTOS task primitives but does not define pdMS_TO_TICKS. If the FreeRTOS include chain changes, this call can fail. Define the 2000 ms value in milliseconds and convert it with FreeRTOS’s tick conversion helper or the local constant used by the FreeRTOS wrapper.

Modules/app-module/include/app/module.h-4-8 (1)

4-8: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Include the Module definition before exposing app_module.

TactilityKernel/include/tactility/module.h defines struct Module. Modules/app-module/include/app/module.h, Modules/app-esp32-module/include/app_esp32/module.h, Modules/gps-module/include/gps/module.h, and Modules/lvgl-module/include/lvgl/module.h declare extern struct Module foo_module; without including it, while Modules/crypt-module/include/crypt/module.h includes tactility/module.h before its declaration. Include TactilityKernel/include/tactility/module.h in the headers that need the full Module type, or change this forward declaration into the same style used by the other leaf module headers if the incomplete type is intentional.

🧹 Nitpick comments (7)
Modules/app-module/private/app/private/app_scheduler.h (1)

10-10: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prefer <stdint.h> in a header that declares C linkage.

The file guards declarations with extern "C", which signals C consumers. <cstdint> compiles only in C++. Use <stdint.h> to keep the header usable from C, and to match include/app/event.h.

♻️ Proposed change
-#include <cstdint>
+#include <stdint.h>
Modules/app-module/source/app_internal_loader.cpp (1)

42-48: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Redundant extern on ServiceManifest definitions in both loader services. An extern declaration with an initializer is a definition, so the keyword has no effect and compilers can warn about it. The same pattern was copied into both modules. Declare each manifest in a header and define it without extern.

  • Modules/app-module/source/app_internal_loader.cpp#L42-L48: remove extern from the app_internal_loader_service_manifest definition.
  • Modules/app-esp32-module/source/app_esp32_loader_service.cpp#L135-L141: remove extern from the loader_service_manifest definition.
Modules/app-module/include/app/location.h (1)

1-16: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add the SPDX header and document the enum values.

Two small gaps in this new header:

  1. Line 1 has no // SPDX-License-Identifier: Apache-2.0. Every other new header in this module has it.
  2. Line 14 points readers to AppLocationType, but that enum documents nothing. State what location holds for each type.
📝 Proposed fix
+// SPDX-License-Identifier: Apache-2.0
 `#pragma` once
 
 `#ifdef` __cplusplus
 extern "C" {
 `#endif`
 
 enum AppLocationType {
+    /** `location` points at an in-memory app image. */
     APP_LOCATION_MEMORY,
+    /** `location` is a NULL-terminated path to the app's install directory. */
     APP_LOCATION_PATH,
 };
Modules/app-module/include/app/metadata.h (1)

1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add the SPDX license identifier.

Every other new file in this change set starts with // SPDX-License-Identifier: Apache-2.0. This header omits it.

📄 Proposed fix
+// SPDX-License-Identifier: Apache-2.0
 `#pragma` once
Modules/app-module/private/app/private/app_metadata_parsing_internal.h (1)

21-24: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Include <cstddef> and qualify std::size_t.

size_t appears unqualified in the global namespace. <map> and <string> only guarantee std::size_t. Mainstream implementations also declare ::size_t, so this compiles today, but the include is not guaranteed.

♻️ Proposed change
+#include <cstddef>
 `#include` <map>
 `#include` <string>
-bool app_metadata_copy_bounded(char* dest, size_t dest_size, const std::string& value);
+bool app_metadata_copy_bounded(char* dest, std::size_t dest_size, const std::string& value);
Modules/app-module/source/app_metadata_parsing_v2.cpp (1)

10-95: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider a shared parse routine driven by a key table.

app_metadata_parse_v2 and app_metadata_parse_v1 differ only in the six property key strings. Every future metadata field needs the same edit in both files. A single routine that accepts a struct of key names removes the duplication.

The internal header documents that the per-format split mirrors the previous tt::app parser, so this is optional.

Modules/app-esp32-module/source/module.cpp (1)

11-11: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Prefix the exported manifest symbol with the module name.

loader_service_manifest is a global symbol with C linkage. Other modules in the image can export the same generic name, which causes a duplicate-symbol link error. Modules/app-module/source/module.cpp uses the prefixed name app_internal_loader_service_manifest. Rename this symbol and its definition to app_esp32_loader_service_manifest.

♻️ Proposed change
-extern ServiceManifest loader_service_manifest;
+extern ServiceManifest app_esp32_loader_service_manifest;
 
 static error_t start() {
-    return service_manager_add(&loader_service_manifest, /*auto_start=*/true);
+    return service_manager_add(&app_esp32_loader_service_manifest, /*auto_start=*/true);
 }
 
 static error_t stop() {
-    return service_manager_remove(loader_service_manifest.id);
+    return service_manager_remove(app_esp32_loader_service_manifest.id);
 }

Rename the definition in Modules/app-esp32-module/source/app_esp32_loader_service.cpp to match.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d42aa53d-a21f-4126-9334-befd7c40d4df

📥 Commits

Reviewing files that changed from the base of the PR and between d2c69ee and f61a307.

📒 Files selected for processing (42)
  • Devices/lilygo-tlora-pager/source/module.cpp
  • Documentation/ideas.md
  • Modules/app-esp32-module/CMakeLists.txt
  • Modules/app-esp32-module/devicetree.yaml
  • Modules/app-esp32-module/include/app_esp32/module.h
  • Modules/app-esp32-module/source/app_esp32_loader_service.cpp
  • Modules/app-esp32-module/source/module.cpp
  • Modules/app-module/CMakeLists.txt
  • Modules/app-module/devicetree.yaml
  • Modules/app-module/include/app/event.h
  • Modules/app-module/include/app/install.h
  • Modules/app-module/include/app/instance.h
  • Modules/app-module/include/app/loader.h
  • Modules/app-module/include/app/location.h
  • Modules/app-module/include/app/manager.h
  • Modules/app-module/include/app/manifest.h
  • Modules/app-module/include/app/metadata.h
  • Modules/app-module/include/app/module.h
  • Modules/app-module/private/app/private/app_ledger.h
  • Modules/app-module/private/app/private/app_metadata_parsing_internal.h
  • Modules/app-module/private/app/private/app_scheduler.h
  • Modules/app-module/source/app_install.cpp
  • Modules/app-module/source/app_internal_loader.cpp
  • Modules/app-module/source/app_metadata_parsing.cpp
  • Modules/app-module/source/app_metadata_parsing_v1.cpp
  • Modules/app-module/source/app_metadata_parsing_v2.cpp
  • Modules/app-module/source/app_scheduler.cpp
  • Modules/app-module/source/event.cpp
  • Modules/app-module/source/manager.cpp
  • Modules/app-module/source/module.cpp
  • Modules/lvgl-window-manager/CMakeLists.txt
  • Modules/lvgl-window-manager/devicetree.yaml
  • Modules/lvgl-window-manager/include/lvgl_window_manager/module.h
  • Modules/lvgl-window-manager/include/lvgl_window_manager/window_manager.h
  • Modules/lvgl-window-manager/source/module.cpp
  • Modules/lvgl-window-manager/source/window_manager.cpp
  • Tactility/Source/lvgl/Statusbar.cpp
  • Tactility/Source/service/rtctime/RtcTimeService.cpp
  • Tactility/Source/service/wifi/Wifi.cpp
  • TactilityKernel/include/tactility/system_event.h
  • TactilityKernel/source/system_event.cpp
  • Tests/TactilityKernel/Source/SystemEventTest.cpp

Comment thread Modules/app-esp32-module/source/app_esp32_loader_service.cpp Outdated
Comment thread Modules/app-esp32-module/source/app_esp32_loader_service.cpp Outdated
Comment thread Modules/app-module/include/app/metadata.h
Comment thread Modules/app-module/source/app_install.cpp
Comment thread Modules/app-module/source/app_install.cpp
Comment thread Modules/lvgl-window-manager-module/source/window_manager.cpp Outdated
Comment thread TactilityKernel/source/system_event.cpp Outdated
Comment thread TactilityKernel/source/system_event.cpp Outdated
Comment thread TactilityKernel/source/system_event.cpp
Comment thread Tests/TactilityKernel/Source/SystemEventTest.cpp

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
TactilityKernel/include/tactility/system_event.h (2)

183-189: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Return a synchronized event snapshot from system_event_await().

system_event_await() only returns ERROR_NONE/ERROR_TIMEOUT; callers cannot read sub->timestamp, sub->data, or sub->data_len through the documented API because those fields are marked internal. The subscription is also latest-value based, so multiple emits before a second await() can overwrite the buffer. Add a supported read/snapshot API and document whether poll events are queued or coalesced.


175-181: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Serialize unsubscription with waiters and re-registration.

system_event_unsubscribe() unlocks poll_subscriptions_mutex before deleting sub->semaphore. A task can still be blocked in system_event_await() on sub->semaphore, and FreeRTOS requires callers not delete a semaphore while tasks are blocked on it. A concurrent re-registration can also replace sub->semaphore before the unsubscribe deletes. Keep the protection held until no one can wait on sub->semaphore, or add cancellation and reference tracking before deletion. Add regression coverage for removal during a blocked await and reuse of the same subscription node.

Modules/lvgl-window-manager-module/source/window_manager.cpp (1)

61-85: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

window_manager_stop() can still delete widgets that a concurrent create or remove is using.

The lifecycle_mutex added in this revision serializes window_manager_start() against window_manager_stop(). It does not cover window_manager_create() or window_manager_remove(). Those functions capture content_root_widget and widget pointers under s.mutex, release s.mutex, and then pass the captured pointers to build_window_widget() and delete_widget().

window_manager_stop() deletes real_root_widget after it releases s.mutex. Deletion cascades to content_root_widget and top_widget. If stop acquires the LVGL lock first, the following lv_obj_create(content) at line 66 or lv_obj_delete(widget) at line 83 operates on a freed lv_obj_t.

Take lifecycle_mutex in window_manager_create() and window_manager_remove() as well, or re-validate started and the captured pointers under s.mutex while holding the LVGL lock before each LVGL call.

Run the following script to confirm that no other synchronization guards this path:

#!/bin/bash
# Description: Check which window-manager functions take lifecycle_mutex, and inspect the lvgl lock implementation.
rg -n -C3 'lifecycle_mutex' Modules/lvgl-window-manager-module/source/window_manager.cpp
echo "=== lvgl_lock / lvgl_unlock definitions ==="
rg -n -C8 '\b(lvgl_lock|lvgl_unlock)\s*\(' Modules/lvgl-module
🧹 Nitpick comments (3)
Modules/app-module/source/manager.cpp (1)

262-314: 🩺 Stability & Availability | 🔵 Trivial | 🏗️ Heavy lift

Do not hold registry.mutex across filesystem I/O and cross-registry calls.

The scan holds registry.mutex from Line 262 to Line 314. Inside that critical section it performs three kinds of blocking or nested work:

  • Line 266 and Line 305 call app_fs_is_file/app_fs_is_directory, which stat each path and take a FileMutex.
  • Line 271 calls app_metadata_parse, which opens and reads the manifest file and also takes a FileMutex.
  • Line 292 and Line 310 call app_manager_add/app_manager_remove, which take the ledger mutex.

Two effects follow. First, a scan over a slow medium such as an SD card blocks app_manager_install_path_add for the whole duration. Second, the code establishes a registry.mutexFileMutex and registry.mutex → ledger-mutex lock order. Any future path that takes those locks in the opposite order deadlocks.

The function already demonstrates the safer pattern at Lines 253-255. Apply it to the rest: do the stat calls and the manifest parsing outside the lock, then take registry.mutex only to publish the resulting records.

Modules/lvgl-window-manager-module/include/lvgl_window_manager/window_manager.h (1)

79-88: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document app_instance_id or remove it.

window_manager_create stores the caller-supplied app_instance_id but the header does not document it and it is never read elsewhere. Add a @param[in] app_instance_id line, or remove the parameter if the value has no consumer.

Modules/lvgl-window-manager-module/source/window_manager.cpp (1)

304-319: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Use a dedicated notification index for window manager waiters.

ulTaskNotifyTake() and xTaskNotifyGive() use notification index 0 by default. If a window-manager waiter also uses task index 0 for its own events, the wait drains those unrelated notifications. Use a dedicated index, such as index 1 (FreeRTOS config already sets configTASK_NOTIFICATION_ARRAY_ENTRIES to 2), and update the waiters and notification senders to use matching indexed APIs.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 07e2b5b3-3c60-4ebb-865f-a8f10170a4cb

📥 Commits

Reviewing files that changed from the base of the PR and between f61a307 and c628668.

📒 Files selected for processing (35)
  • Buildscripts/TactilitySDK/CMakeLists.txt
  • Buildscripts/TactilitySDK/TactilitySDK.cmake
  • Buildscripts/release-sdk.py
  • CMakeLists.txt
  • Devices/lilygo-tdeck-plus/device.properties
  • Documentation/ideas.md
  • Modules/app-esp32-module/source/app_esp32_loader_service.cpp
  • Modules/app-module/include/app/instance.h
  • Modules/app-module/include/app/manager.h
  • Modules/app-module/include/app/metadata.h
  • Modules/app-module/include/app/scheduler.h
  • Modules/app-module/private/app/private/app_fs.h
  • Modules/app-module/private/app/private/app_ledger.h
  • Modules/app-module/private/app/private/app_scheduler.h
  • Modules/app-module/source/app_install.cpp
  • Modules/app-module/source/app_metadata_parsing.cpp
  • Modules/app-module/source/app_metadata_parsing_v1.cpp
  • Modules/app-module/source/app_metadata_parsing_v2.cpp
  • Modules/app-module/source/app_scheduler.cpp
  • Modules/app-module/source/manager.cpp
  • Modules/app-module/source/symbols.cpp
  • Modules/lvgl-window-manager-module/CMakeLists.txt
  • Modules/lvgl-window-manager-module/devicetree.yaml
  • Modules/lvgl-window-manager-module/include/lvgl_window_manager/module.h
  • Modules/lvgl-window-manager-module/include/lvgl_window_manager/window_manager.h
  • Modules/lvgl-window-manager-module/source/symbols.cpp
  • Modules/lvgl-window-manager-module/source/window_manager.cpp
  • TactilityKernel/include/tactility/system_event.h
  • TactilityKernel/source/system_event.cpp
  • Tests/CMakeLists.txt
  • Tests/Tactility/CMakeLists.txt
  • Tests/app-module/CMakeLists.txt
  • Tests/app-module/Source/AppEventTest.cpp
  • Tests/app-module/Source/AppManagerTest.cpp
  • Tests/app-module/Source/Main.cpp
🚧 Files skipped from review as they are similar to previous changes (8)
  • Modules/app-module/private/app/private/app_ledger.h
  • Modules/app-module/source/app_metadata_parsing_v1.cpp
  • Modules/app-module/source/app_metadata_parsing_v2.cpp
  • Modules/app-module/private/app/private/app_scheduler.h
  • Modules/app-module/include/app/metadata.h
  • Modules/app-esp32-module/source/app_esp32_loader_service.cpp
  • TactilityKernel/source/system_event.cpp
  • Modules/app-module/source/app_install.cpp

Comment thread Buildscripts/TactilitySDK/CMakeLists.txt
Comment thread Documentation/ideas.md Outdated
Comment thread Modules/app-module/private/app/private/app_fs.h
Comment thread Modules/app-module/source/app_scheduler.cpp
Comment thread Modules/app-module/source/app_scheduler.cpp
Comment thread Modules/app-module/source/symbols.cpp
Comment thread Modules/lvgl-window-manager-module/source/window_manager.cpp Outdated
Comment thread Tests/app-module/Source/AppManagerTest.cpp
Comment thread Tests/app-module/Source/Main.cpp

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🧹 Nitpick comments (1)
Modules/app-esp32-module/LICENSE-Apache-2.0.md (1)

7-9: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Exclude the Apache license files from Markdown lint.

The three added license files trigger the same MD001 and MD003 warnings. Preserve the legal boilerplate and exclude these files from the Markdown rules.

  • Modules/app-esp32-module/LICENSE-Apache-2.0.md#L7-L9: Exclude this license file from Markdown lint.
  • Modules/app-module/LICENSE-Apache-2.0.md#L7-L9: Exclude this license file from Markdown lint.
  • Modules/lvgl-window-manager-module/LICENSE-Apache-2.0.md#L7-L9: Exclude this license file from Markdown lint.

Source: Linters/SAST tools


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 34578dc8-8095-4c70-abc3-82ad0e591548

📥 Commits

Reviewing files that changed from the base of the PR and between c628668 and 1ae6e77.

📒 Files selected for processing (48)
  • Buildscripts/TactilitySDK/CMakeLists.txt
  • Documentation/ideas.md
  • Modules/app-esp32-module/LICENSE-Apache-2.0.md
  • Modules/app-module/LICENSE-Apache-2.0.md
  • Modules/app-module/include/app/location.h
  • Modules/app-module/include/app/manager.h
  • Modules/app-module/include/app/metadata.h
  • Modules/app-module/include/app/module.h
  • Modules/app-module/include/app/paths.h
  • Modules/app-module/private/app/private/app_fs.h
  • Modules/app-module/private/app/private/app_ledger.h
  • Modules/app-module/private/app/private/app_scheduler.h
  • Modules/app-module/source/app_install.cpp
  • Modules/app-module/source/app_internal_loader.cpp
  • Modules/app-module/source/app_paths.cpp
  • Modules/app-module/source/app_scheduler.cpp
  • Modules/app-module/source/symbols.cpp
  • Modules/lvgl-window-manager-module/LICENSE-Apache-2.0.md
  • Modules/lvgl-window-manager-module/include/lvgl_window_manager/window_manager.h
  • Modules/lvgl-window-manager-module/source/window_manager.cpp
  • TactilityC/Include/tt_app.h
  • TactilityC/Include/tt_app_alertdialog.h
  • TactilityC/Include/tt_app_fileselection.h
  • TactilityC/Include/tt_app_selectiondialog.h
  • TactilityC/Include/tt_bundle.h
  • TactilityC/Include/tt_preferences.h
  • TactilityC/Source/tt_app.cpp
  • TactilityC/Source/tt_app_alertdialog.cpp
  • TactilityC/Source/tt_app_fileselection.cpp
  • TactilityC/Source/tt_app_selectiondialog.cpp
  • TactilityC/Source/tt_bundle.cpp
  • TactilityC/Source/tt_init.cpp
  • TactilityC/Source/tt_preferences.cpp
  • TactilityKernel/include/tactility/bundle.h
  • TactilityKernel/include/tactility/preferences.h
  • TactilityKernel/include/tactility/properties_file.h
  • TactilityKernel/include/tactility/system_event.h
  • TactilityKernel/source/bundle.cpp
  • TactilityKernel/source/preferences.cpp
  • TactilityKernel/source/properties_file.cpp
  • TactilityKernel/source/symbols.c
  • TactilityKernel/source/system_event.cpp
  • Tests/TactilityKernel/Source/BundleTest.cpp
  • Tests/TactilityKernel/Source/PreferencesTest.cpp
  • Tests/TactilityKernel/Source/PropertiesFileTest.cpp
  • Tests/TactilityKernel/Source/SystemEventTest.cpp
  • Tests/app-module/Source/AppManagerTest.cpp
  • Tests/app-module/Source/Main.cpp
💤 Files with no reviewable changes (8)
  • TactilityC/Include/tt_preferences.h
  • TactilityC/Source/tt_preferences.cpp
  • TactilityC/Include/tt_bundle.h
  • TactilityC/Source/tt_bundle.cpp
  • TactilityC/Include/tt_app.h
  • Modules/app-module/private/app/private/app_scheduler.h
  • TactilityC/Source/tt_init.cpp
  • TactilityC/Source/tt_app.cpp
🚧 Files skipped from review as they are similar to previous changes (13)
  • Modules/app-module/include/app/module.h
  • Modules/app-module/source/app_internal_loader.cpp
  • Modules/app-module/private/app/private/app_ledger.h
  • Modules/app-module/source/symbols.cpp
  • Modules/app-module/private/app/private/app_fs.h
  • Buildscripts/TactilitySDK/CMakeLists.txt
  • Tests/app-module/Source/AppManagerTest.cpp
  • Modules/lvgl-window-manager-module/include/lvgl_window_manager/window_manager.h
  • Modules/app-module/include/app/metadata.h
  • Modules/app-module/include/app/location.h
  • Modules/lvgl-window-manager-module/source/window_manager.cpp
  • Modules/app-module/include/app/manager.h
  • Modules/app-module/source/app_install.cpp

Comment thread Modules/app-module/source/app_scheduler.cpp
Comment thread TactilityC/Include/tt_app_fileselection.h Outdated
Comment thread TactilityC/Source/tt_app_fileselection.cpp
Comment thread TactilityKernel/source/bundle.cpp
Comment thread TactilityKernel/source/preferences.cpp
Comment thread TactilityKernel/source/preferences.cpp
Comment thread TactilityKernel/source/properties_file.cpp Outdated
Comment thread TactilityKernel/source/system_event.cpp Outdated
Comment thread TactilityKernel/source/system_event.cpp Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (4)
Tests/TactilityKernel/Source/PreferencesTest.cpp (1)

233-237: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Guard the reopened handle like the first one.

Line 224 uses REQUIRE_NE(preferences, nullptr). Line 233 omits the same check for reopened. If the reopen fails, Line 235 passes nullptr into preferences_opt_int32, which dereferences it and crashes the test binary instead of reporting a failed assertion.

♻️ Proposed change
     Preferences* reopened = preferences_open(nested_path);
+    REQUIRE_NE(reopened, nullptr);
     int32_t out = 0;
     CHECK(preferences_opt_int32(reopened, "count", &out));
Tests/TactilityKernel/Source/SystemEventTest.cpp (1)

402-404: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Two thread_join calls use a 2-tick timeout. Both new tests join a worker thread with a 2-tick timeout and a 1-tick poll interval. That margin does not cover the worker's return path and thread-completion bookkeeping on a loaded CI runner, so either join can fail for a scheduling reason rather than a code defect.

  • Tests/TactilityKernel/Source/SystemEventTest.cpp#L402-L404: raise the join timeout for the awaiter thread; Line 400 already bounds the timing the test cares about.
  • Tests/TactilityKernel/Source/SystemEventTest.cpp#L435-L436: raise the join timeout for the emitter thread; the await at Line 434 already bounds the timing.

Use pdMS_TO_TICKS(2000) for the timeout and pdMS_TO_TICKS(1) for the poll interval at both sites.

Modules/lvgl-window-manager-module/source/window_manager.cpp (2)

4-4: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the module include path for app/instance.h.

lvgl-window-manager-module includes app-module through REQUIRES, and app-module exports include/. Add app-module to REQUIRES and change both app/instance.h includes in Modules/lvgl-window-manager-module to #include <app/instance.h> instead of relative ../../../ / ../../app-module/include/... paths.


273-294: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document the non-reentrancy limit for window-manager callbacks.

lifecycle_mutex is held during screen_init(), create_widgets(), and the rebuild path in window_manager_remove(). Because Mutex is not recursive, calling any window-manager API from these callbacks can deadlock. Add this restriction to WindowManagerScreenInitFn and WindowCreateWidgetsFn in window_manager.h.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7bb353d5-9b14-478c-b6d1-af16d83ad636

📥 Commits

Reviewing files that changed from the base of the PR and between 1ae6e77 and ba59437.

📒 Files selected for processing (19)
  • Firmware/CMakeLists.txt
  • Modules/app-esp32-module/source/app_esp32_loader_service.cpp
  • Modules/app-module/private/app/private/app_ledger.h
  • Modules/app-module/source/app_scheduler.cpp
  • Modules/app-module/source/manager.cpp
  • Modules/lvgl-window-manager-module/include/lvgl_window_manager/window_manager.h
  • Modules/lvgl-window-manager-module/source/window_manager.cpp
  • Tactility/CMakeLists.txt
  • TactilityC/Include/tt_app_fileselection.h
  • TactilityKernel/include/tactility/preferences.h
  • TactilityKernel/include/tactility/properties_file.h
  • TactilityKernel/include/tactility/system_event.h
  • TactilityKernel/source/bundle.cpp
  • TactilityKernel/source/preferences.cpp
  • TactilityKernel/source/properties_file.cpp
  • TactilityKernel/source/system_event.cpp
  • Tests/TactilityKernel/Source/PreferencesTest.cpp
  • Tests/TactilityKernel/Source/PropertiesFileTest.cpp
  • Tests/TactilityKernel/Source/SystemEventTest.cpp
🚧 Files skipped from review as they are similar to previous changes (8)
  • TactilityKernel/source/bundle.cpp
  • Modules/app-esp32-module/source/app_esp32_loader_service.cpp
  • TactilityKernel/include/tactility/preferences.h
  • TactilityC/Include/tt_app_fileselection.h
  • TactilityKernel/source/preferences.cpp
  • Modules/app-module/source/manager.cpp
  • TactilityKernel/source/system_event.cpp
  • Modules/lvgl-window-manager-module/include/lvgl_window_manager/window_manager.h

Comment thread Modules/app-module/source/app_scheduler.cpp
Comment thread Tactility/CMakeLists.txt Outdated
Comment thread TactilityKernel/include/tactility/system_event.h
Comment thread TactilityKernel/source/properties_file.cpp
Comment thread Tests/TactilityKernel/Source/PropertiesFileTest.cpp Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
TactilityKernel/source/system_event.cpp (1)

238-275: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Wake every blocked awaiter during removal.

xSemaphoreGive() unblocks only one task waiting on a binary semaphore. If two tasks call system_event_await() on the same subscription, system_event_unsubscribe() wakes one and then waits for waiter_count to reach zero indefinitely while the other task remains blocked.

Signal each blocked awaiter, or reject concurrent system_event_await() calls on one subscription and document that restriction.

♻️ Duplicate comments (1)
TactilityKernel/source/bundle.cpp (1)

47-47: 🩺 Stability & Availability | 🟠 Major

Restore allocation-failure handling for bundle_clone.

Line 47 copies an std::unordered_map whose nodes, keys, and string values can allocate. new (std::nothrow) only protects the initial Bundle allocation. If this copy fails, std::bad_alloc escapes instead of returning nullptr.

Restore a fallible clone path. When exceptions are enabled, catch the allocation failure, free clone, and return nullptr. When exceptions are disabled, use a non-throwing storage and copy design.

Possible fix when C++ exceptions are enabled
-    clone->entries = bundle->entries;
+    try {
+        clone->entries = bundle->entries;
+    } catch (const std::bad_alloc&) {
+        delete clone;
+        return nullptr;
+    }

Run this verification script:

#!/usr/bin/env bash
set -euo pipefail

echo "== Exception configuration =="
rg -n -C 3 \
  'fno-exceptions|fexceptions|CMAKE_CXX_FLAGS|CXX_FLAGS|CXX_STANDARD|exceptions' \
  . || true

echo "== Bundle definition and clone callers =="
rg -n -C 6 \
  '\bbundle_clone\s*\(|\bstruct Bundle\b|std::unordered_map|entries' \
  TactilityKernel Tests Modules || true

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 280abc30-8250-42d6-a7ad-ad8bd0e0772c

📥 Commits

Reviewing files that changed from the base of the PR and between ba59437 and a2056e8.

📒 Files selected for processing (13)
  • Modules/app-module/source/app_scheduler.cpp
  • Modules/lvgl-window-manager-module/CMakeLists.txt
  • Modules/lvgl-window-manager-module/include/lvgl_window_manager/window_manager.h
  • Modules/lvgl-window-manager-module/source/window_manager.cpp
  • Tactility/CMakeLists.txt
  • TactilityKernel/include/tactility/properties_file.h
  • TactilityKernel/include/tactility/system_event.h
  • TactilityKernel/source/bundle.cpp
  • TactilityKernel/source/properties_file.cpp
  • TactilityKernel/source/system_event.cpp
  • Tests/TactilityKernel/Source/PreferencesTest.cpp
  • Tests/TactilityKernel/Source/PropertiesFileTest.cpp
  • Tests/TactilityKernel/Source/SystemEventTest.cpp
🚧 Files skipped from review as they are similar to previous changes (10)
  • Modules/lvgl-window-manager-module/CMakeLists.txt
  • Tests/TactilityKernel/Source/PreferencesTest.cpp
  • TactilityKernel/include/tactility/properties_file.h
  • Modules/app-module/source/app_scheduler.cpp
  • TactilityKernel/source/properties_file.cpp
  • Tests/TactilityKernel/Source/PropertiesFileTest.cpp
  • Modules/lvgl-window-manager-module/include/lvgl_window_manager/window_manager.h
  • Tests/TactilityKernel/Source/SystemEventTest.cpp
  • Tactility/CMakeLists.txt
  • Modules/lvgl-window-manager-module/source/window_manager.cpp

Comment thread TactilityKernel/include/tactility/system_event.h
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant