App Model
This page describes the base app types in System Core, the native and runtime integration paths, and the full lifecycle state transitions.
Base Types
Type |
Description |
|---|---|
|
The runtime app id assigned by the core; |
|
The app timer id assigned by the core; |
|
App source, currently |
|
App state, currently |
|
GUI root source, currently |
|
App install, display, and runtime information |
|
GUI root, startup screen flows, and GUI resources |
|
|
App Manifest
Field |
Description |
|---|---|
|
Unique app manifest id |
|
Current default display name |
|
Localized display names, keyed by language |
|
App version, defaults to |
|
|
|
Whether it appears in app lists such as the launcher |
|
Display icon image id; for a runtime package, filled from the runtime root |
|
Supported system type list; an empty array means no restriction |
|
App icon |
|
Runtime backend type |
|
Runtime package root directory |
|
Runtime entry file |
|
App resource directory |
|
Runtime startup arguments |
Native App Versus Runtime App
Dimension |
Native App |
Runtime App |
|---|---|---|
Integration |
C++ subclass of |
Unpacked package manifest + scripted convention functions |
|
|
|
Install source |
|
|
Lifecycle |
C++ virtual functions |
|
GUI operations |
|
|
Timer |
|
|
Permission |
Currently treated as a trusted built-in app |
Regular app, can only operate its own resources |
App Lifecycle
Install. Native app: install_app() reads IApp::get_manifest(), the core forces manifest.kind = AppKind::Native, reads get_gui_descriptor() and validates the startup screen flow target, allocates an AppId and creates an AppContext, calls IApp::on_install(), writes the app table, and calls on_app_installed(). Runtime app: install_runtime_app() receives an AppManifest, the core forces manifest.kind = AppKind::Runtime, reads the resource descriptor from <runtime.resource_dir>/profile.json and validates screen_flows[], allocates an AppId and creates an AppContext, writes the app table, and calls on_app_installed().
The start_app() order:
Set the state to
Starting.A native app auto-registers the resources in the GUI descriptor.
Load the app-owned GUI document according to the GUI descriptor.
If the descriptor configures
screen_flows[], the core auto-starts the corresponding flow and mountsinitialto the logical layer.A native app calls
IApp::on_start().A runtime app calls
load_app(), thenstart_app(), thenbrookesia_app.on_start().On success the state becomes
Running, the active app is updated, andon_app_started()is called.
If resource registration, GUI loading, or a lifecycle step fails, the core unloads the loaded GUI, unregisters the registered resources, and sets the state to Error.
The stop_app() order:
Set the state to
Stopping.Cancel all timers of the app and clear pending timers.
A native app calls
IApp::on_stop(); a runtime app callsbrookesia_app.on_stop()and then stops the runtime app.Disconnect actions, stop the app-owned running screen flow, and unload the GUI document.
Unregister app image/font resources.
On success the state becomes
Stopped; if it was the active app the active app is cleared, andon_app_stopped()is called.
uninstall_app() first stops a Running or Paused app, then calls on_uninstall() or brookesia_app.on_uninstall(), cancels timers, unloads the runtime, unloads the GUI document, unregisters GUI resources, and removes it from the app table and manifest id index.
pause_app() calls on_pause() and the state becomes Paused; resume_app() calls on_resume() and the state becomes Running again and updates the active app. The current implementation does not auto-unmount the GUI or stop timers on pause; an app should handle special needs in its callbacks.
Native App Integration
A native app integrates by subclassing core::IApp in C++, usually including the compatibility entry brookesia/system_core/app.hpp. The current IApp interface:
Function |
Description |
|---|---|
|
Required; returns the app manifest |
|
Optional; returns the GUI root, startup screen flows, and image/font resources |
|
Install/uninstall callbacks; succeed by default |
|
Start/stop callbacks; succeed by default |
|
Pause/resume callbacks; succeed by default |
|
Called when a GUI action is dispatched; succeeds by default |
|
Called when an app timer fires; succeeds by default |
start_app() auto-registers the resources returned by get_gui_descriptor() and loads the GUI document before on_start(); if screen_flows[] is configured, it also auto-mounts the initial screen of that flow. on_start() is a no-op success by default; a visible UI app usually overrides it to initialize text, bindings, actions, timers, and other business state.
AppContext provides app_id(), system_service(), timer(), and gui(). system_service() returns SystemApi; a native app is currently treated as a trusted built-in app and can start/stop any app, read the storage layout, access its own cache/data/files and public directories, and adjust the runtime app default install target.
IAppProvider registers apps linked into the project at compile time: get_manifest() returns the provider's manifest, and create_app() returns a native app instance (when empty, it is installed as a runtime manifest). Registration macro:
BROOKESIA_SYSTEM_CORE_APP_PROVIDER_REGISTER_WITH_SYMBOL(ProviderType, name, symbol_name)
System::install_registered_apps() iterates the AppProviderRegistry and installs the apps the providers supply.
Runtime App Integration
A runtime app integrates through an unpacked package and scripted convention functions and does not include C++ headers. When install_package_apps = true, System::init() scans the apps directories under internal and external storage in the layout:
<storage-root>/apps/
brookesia.app.calculator/
manifest.json
app/
app.lua
res/
profile.json
root.json
The core scans the first-level directories that contain manifest.json under each app root and loads them sorted by directory path. manifest.json is parsed by read_unpacked_app_manifest(), with this mapping:
Package Field |
Maps To |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
runtime.entry and runtime.resource_dir must be safe relative paths, not absolute and not containing ..; a package whose package.systems does not match the current system type is skipped. The script entry must create a global table brookesia_app, and the core calls the convention functions through the runtime:
brookesia_app.on_install()/brookesia_app.on_uninstall()brookesia_app.on_start()/brookesia_app.on_stop()brookesia_app.on_pause()/brookesia_app.on_resume()brookesia_app.on_action(action)brookesia_app.on_timer(timer_id, name)
A missing function is treated as a no-op; a function that returns false or throws fails the corresponding lifecycle step, and the app may enter Error. The runtime app GUI document comes from the root of <runtime.resource_dir>/profile.json, and the startup flow is written in screen_flows[]; see App Package.