mirror of
https://github.com/apache/nuttx-apps.git
synced 2026-10-07 14:15:13 +00:00
system/nxstore: add LVGL app-store UI.
Add nxstore, an LVGL-based frontend for nxpkg (system/nxpkg): lists packages from the local index, installs/launches the selected one, and supervises whatever it hands the screen to. Card-based app list (populate_app_list()): each row shows name, version, and description/status, install/launch state reflected via icon glyph and color (LV_SYMBOL_DOWNLOAD/PLAY, accent/success color), and a sliding-segment progress bar during install (no real byte-level progress is available from pkg_install(), so this reads as 'actively working' without fabricating a percentage). Explicit LV_STATE_PRESSED styling on every tappable row/button, since no LVGL theme is loaded and a tap would otherwise give no visual feedback at all. Supervisor screen (build_run_screen()/nxstore_enter_running_screen()): a launched app (e.g. a game that owns /dev/fb0 directly, not just another LVGL client) gets a dedicated screen with a name label and a Close button, confined to the border region the launched app's own scaled/centered framebuffer output never draws into, so switching back to it doesn't fight over pixels with whatever the app already put in the framebuffer. Close/reap handling (close_running_app_event_cb()/ nxstore_poll_running_app()): sends SIGTERM and polls waitpid(WNOHANG) for the launched pid, but explicitly also treats waitpid() returning ECHILD as 'already gone' rather than 'still running' - both the close-button handler and the passive per-loop poll independently race to reap the same child, so whichever one loses that race must not spin forever waiting for a wait() that can now never succeed. Requires the target app to install its own SIGTERM handler to exit cleanly (this is why there is no generic force-kill fallback here: an earlier version of this code called task_delete() when SIGTERM wasn't reaped quickly enough, which was found on real hardware to hang the entire board - not just the one task - when it landed mid framebuffer/heap access on this flat-memory build). Toast notifications (nxstore_toast()) provide a transient, unmissable confirmation for install/uninstall/launch outcomes and app-closed events, additive to the durable per-row subtitle text rather than a replacement for it. nxstore's own boot-time catalog sync waits (bounded, 15s) on g_wifi_dhcp_ret before attempting a network fetch, since Wi-Fi association completing doesn't imply DHCP has - an HTTP fetch attempted in that window fails with -ENETUNREACH even though the link itself is already up, indistinguishable from being genuinely offline without this wait. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: aviralgarg05 <gargaviral99@gmail.com>
This commit is contained in:
parent
f363a8f444
commit
778bc0e64c
6 changed files with 1905 additions and 0 deletions
35
system/nxstore/CMakeLists.txt
Normal file
35
system/nxstore/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# ##############################################################################
|
||||
# apps/system/nxstore/CMakeLists.txt
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more contributor
|
||||
# license agreements. See the NOTICE file distributed with this work for
|
||||
# additional information regarding copyright ownership. The ASF licenses this
|
||||
# file to you under the Apache License, Version 2.0 (the "License"); you may not
|
||||
# use this file except in compliance with the License. You may obtain a copy of
|
||||
# the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations under
|
||||
# the License.
|
||||
#
|
||||
# ##############################################################################
|
||||
|
||||
if(CONFIG_SYSTEM_NXSTORE)
|
||||
nuttx_add_application(
|
||||
NAME
|
||||
${CONFIG_SYSTEM_NXSTORE_PROGNAME}
|
||||
PRIORITY
|
||||
${CONFIG_SYSTEM_NXSTORE_PRIORITY}
|
||||
STACKSIZE
|
||||
${CONFIG_SYSTEM_NXSTORE_STACKSIZE}
|
||||
MODULE
|
||||
${CONFIG_SYSTEM_NXSTORE}
|
||||
SRCS
|
||||
nxstore_main.c)
|
||||
endif()
|
||||
30
system/nxstore/Kconfig
Normal file
30
system/nxstore/Kconfig
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
|
||||
config SYSTEM_NXSTORE
|
||||
tristate "Nxstore LVGL App Store"
|
||||
default n
|
||||
depends on GRAPHICS_LVGL && SYSTEM_NXPKG
|
||||
select NETUTILS_CJSON
|
||||
---help---
|
||||
Enable the Nxstore LVGL graphical application store frontend.
|
||||
Lists packages from the local nxpkg repository, installs the
|
||||
selected one via nxpkg, and launches it.
|
||||
|
||||
if SYSTEM_NXSTORE
|
||||
|
||||
config SYSTEM_NXSTORE_PROGNAME
|
||||
string "Program name"
|
||||
default "nxstore"
|
||||
|
||||
config SYSTEM_NXSTORE_PRIORITY
|
||||
int "nxstore task priority"
|
||||
default 100
|
||||
|
||||
config SYSTEM_NXSTORE_STACKSIZE
|
||||
int "nxstore stack size"
|
||||
default 8192
|
||||
|
||||
endif
|
||||
25
system/nxstore/Make.defs
Normal file
25
system/nxstore/Make.defs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
############################################################################
|
||||
# apps/system/nxstore/Make.defs
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
ifneq ($(CONFIG_SYSTEM_NXSTORE),)
|
||||
CONFIGURED_APPS += $(APPDIR)/system/nxstore
|
||||
endif
|
||||
32
system/nxstore/Makefile
Normal file
32
system/nxstore/Makefile
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
############################################################################
|
||||
# apps/system/nxstore/Makefile
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
include $(APPDIR)/Make.defs
|
||||
|
||||
PROGNAME = $(CONFIG_SYSTEM_NXSTORE_PROGNAME)
|
||||
PRIORITY = $(CONFIG_SYSTEM_NXSTORE_PRIORITY)
|
||||
STACKSIZE = $(CONFIG_SYSTEM_NXSTORE_STACKSIZE)
|
||||
MODULE = $(CONFIG_SYSTEM_NXSTORE)
|
||||
|
||||
MAINSRC = nxstore_main.c
|
||||
|
||||
include $(APPDIR)/Application.mk
|
||||
100
system/nxstore/README.txt
Normal file
100
system/nxstore/README.txt
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
nxstore - an LVGL touchscreen app store for NuttX
|
||||
=================================================
|
||||
|
||||
nxstore is a graphical front-end for system/nxpkg. It lists the
|
||||
packages available in a nxpkg repository, installs the one you tap via
|
||||
nxpkg, launches it, and supervises it with an on-screen "Close"
|
||||
control. It is the touchscreen equivalent of driving the nxpkg CLI by
|
||||
hand; both consume the same repository, so the repository/server setup
|
||||
(layout, how to serve it, populating it with tools/export_pkg_repo.py,
|
||||
pointing the board at it) is documented once, in system/nxpkg's
|
||||
README.txt, and is not repeated here.
|
||||
|
||||
|
||||
Dependencies
|
||||
============
|
||||
|
||||
Kconfig: SYSTEM_NXSTORE depends on GRAPHICS_LVGL and SYSTEM_NXPKG and
|
||||
selects NETUTILS_CJSON. It needs a working framebuffer (/dev/fb0) and
|
||||
a touch input device (/dev/input0) - the same graphics/input stack
|
||||
examples/lvgldemo uses. NETUTILS_CJSON is used to parse the
|
||||
repository index and package manifests.
|
||||
|
||||
|
||||
On-device lifecycle
|
||||
===================
|
||||
|
||||
1. Browse - the app list is built from the repository index nxpkg
|
||||
fetched. Installed packages show a launch action;
|
||||
not-yet-installed ones show an install action.
|
||||
2. Install - tapping an uninstalled package runs the nxpkg install
|
||||
flow (download -> sha256 verify -> transactional
|
||||
install) on a background worker thread, with progress
|
||||
shown as a toast.
|
||||
3. Launch - tapping an installed package spawns its payload
|
||||
(posix_spawn) and switches to the "running" screen: a
|
||||
thin bar across the top NXSTORE_BAR_HEIGHT pixels (see
|
||||
include/system/nxstore_chrome.h) carrying the app name
|
||||
and a Close button, with the rest of the framebuffer
|
||||
left to the running app.
|
||||
4. Close - see "Closing a running app" below.
|
||||
|
||||
Launched apps are given NXSTORE_LAUNCH_STACKSIZE (32 KiB) of stack -
|
||||
posix_spawn's default (CONFIG_POSIX_SPAWN_DEFAULT_STACKSIZE, 2 KiB) is
|
||||
far too small for a real LVGL/framebuffer app, and overflowing it does
|
||||
not fail loudly (it corrupts adjacent heap, surfacing later as a crash
|
||||
nowhere near the real cause).
|
||||
|
||||
|
||||
Closing a running app: the cooperative-SIGTERM contract
|
||||
=======================================================
|
||||
|
||||
This is the one thing an app author MUST get right to be launchable
|
||||
from nxstore.
|
||||
|
||||
The Close button sends the running app SIGTERM and waits for it to
|
||||
reap itself. It does NOT (and cannot safely) force-kill the task:
|
||||
|
||||
- On a build with CONFIG_SIG_DEFAULT disabled (the default), NuttX
|
||||
has no default action for SIGTERM at all. Delivery does nothing
|
||||
unless the app installs its own handler with sigaction().
|
||||
- An earlier nxstore fell back to task_delete() when SIGTERM went
|
||||
unreaped. On real hardware that force-kill landed while the app
|
||||
was mid framebuffer/heap access and hung the *entire board* (not
|
||||
just the task), requiring a physical power cycle. That fallback
|
||||
was removed: there is no safe way to force-terminate an arbitrary
|
||||
task from the outside here.
|
||||
|
||||
So an nxstore-launchable app must cooperate:
|
||||
|
||||
- Install an async-signal-safe SIGTERM handler that only sets a
|
||||
volatile sig_atomic_t flag.
|
||||
- Poll that flag from its own main loop and exit cleanly (freeing
|
||||
the framebuffer, restoring input state, etc.) when it is set.
|
||||
|
||||
Apps whose main loop can never block indefinitely (they run to
|
||||
completion on their own, or fail fast at startup) do not strictly need
|
||||
a handler, but any app that renders in a long-lived loop does. See
|
||||
these in-tree examples for the exact pattern:
|
||||
|
||||
- games/NXDoom (i_install_quit_signal / i_poll_quit_signal)
|
||||
- examples/calculator
|
||||
- games/cgol, games/brickmatch
|
||||
|
||||
If SIGTERM is not reaped within the timeout, nxstore keeps the running
|
||||
screen up rather than returning to the app list - switching back while
|
||||
the app might still be alive and drawing into the framebuffer would
|
||||
just reproduce the original hang, hidden.
|
||||
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
SYSTEM_NXSTORE_PROGNAME program/registration name (default nxstore)
|
||||
SYSTEM_NXSTORE_PRIORITY task priority (default 100)
|
||||
SYSTEM_NXSTORE_STACKSIZE nxstore's own stack (default 8192)
|
||||
|
||||
NXSTORE_LAUNCH_STACKSIZE (the stack given to launched apps) and
|
||||
NXSTORE_BAR_HEIGHT (the reserved top bar) are compile-time constants in
|
||||
the source / include/system/nxstore_chrome.h rather than Kconfig
|
||||
options.
|
||||
1683
system/nxstore/nxstore_main.c
Normal file
1683
system/nxstore/nxstore_main.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue