From: Simon Glass <simon.glass@canonical.com> Add a helper function that checks the 'expo_log_filter' environment variable. If not set, all objects are logged. If set, it contains a comma-separated list of filters; only objects whose name contains one of the filter strings are logged. The feature is controlled by CONFIG_EXPO_LOG_FILTER, which is enabled by default for sandbox. Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- boot/Kconfig | 10 ++++++++++ boot/scene.c | 32 ++++++++++++++++++++++++++++++++ boot/scene_internal.h | 12 ++++++++++++ doc/develop/expo.rst | 27 +++++++++++++++++++++++++++ test/boot/expo.c | 37 +++++++++++++++++++++++++++++++++++++ 5 files changed, 118 insertions(+) diff --git a/boot/Kconfig b/boot/Kconfig index 7ff0dedb748..14b7ed573c9 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -1002,6 +1002,16 @@ config EXPO_TEST variable is set to 1. This is useful for debugging and performance analysis. +config EXPO_LOG_FILTER + bool "Enable expo log filter" + depends on EXPO + default y if SANDBOX + help + Enable the expo log filter. When enabled, the 'expo_log_filter' + environment variable can be set to filter log output by object name. + Only objects whose name contains the filter string are logged. This + is useful for debugging specific expo objects. + config BOOTMETH_SANDBOX def_bool y depends on SANDBOX diff --git a/boot/scene.c b/boot/scene.c index 3565bfd77de..9cade9aad41 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -10,6 +10,7 @@ #include <alist.h> #include <dm.h> +#include <env.h> #include <expo.h> #include <malloc.h> #include <mapmem.h> @@ -42,6 +43,37 @@ static const char *const scene_obj_type_names[] = { "textline", }; +bool scene_chklog(const char *name) +{ + const char *filter, *end, *p; + int len; + + if (!CONFIG_IS_ENABLED(EXPO_LOG_FILTER)) + return true; + + filter = env_get("expo_log_filter"); + if (!filter) + return true; + + /* Check each comma-separated filter */ + while (*filter) { + end = strchrnul(filter, ','); + len = end - filter; + + /* Check if this filter segment appears in name */ + for (p = name; *p; p++) { + if (!strncmp(p, filter, len)) + return true; + } + + if (!*end) + break; + filter = end + 1; + } + + return false; +} + int scene_new(struct expo *exp, const char *name, uint id, struct scene **scnp) { struct scene *scn; diff --git a/boot/scene_internal.h b/boot/scene_internal.h index db11f9c0f60..d3c67777cb1 100644 --- a/boot/scene_internal.h +++ b/boot/scene_internal.h @@ -613,6 +613,18 @@ int scene_calc_arrange(struct scene *scn, struct expo_arrange_info *arr); int scene_txt_generic_init(struct expo *exp, struct scene_txt_generic *gen, const char *name, uint str_id, const char *str); +/** + * scene_chklog() - Check if logging is enabled for an object + * + * This checks the 'expo_log_filter' environment variable. If not set, all + * objects are logged. If set, it contains a comma-separated list of filters; + * only objects whose name contains one of the filter strings are logged. + * + * @name: Object name to check + * Return: true if logging should happen, false to skip + */ +bool scene_chklog(const char *name); + /** * scene_flag_name() - Get the name of a scene flag * diff --git a/doc/develop/expo.rst b/doc/develop/expo.rst index fc642ed3696..7ef714be3da 100644 --- a/doc/develop/expo.rst +++ b/doc/develop/expo.rst @@ -605,6 +605,33 @@ These metrics help identify performance bottlenecks and verify that expo is operating efficiently. The timing information is particularly useful when optimizing display drivers or debugging slow rendering issues. +Log filter +~~~~~~~~~~ + +Expo supports filtering log output by object name, which is useful when +debugging specific objects. Set the ``expo_log_filter`` environment variable +to a substring that matches the object names you want to log. + +To enable log filtering:: + + => setenv expo_log_filter texted + => log filter-add -d console -A -c expo -l debug + +This shows debug logs only for objects whose name contains "texted". + +Multiple filters can be specified as a comma-separated list:: + + => setenv expo_log_filter menu,text + +This logs objects matching either "menu" or "text". + +Remove the filter to see all objects:: + + => setenv expo_log_filter + +This feature requires ``CONFIG_EXPO_LOG_FILTER`` which is enabled by default +for sandbox. + Writing expo tests ------------------ diff --git a/test/boot/expo.c b/test/boot/expo.c index 97b9bf82bb7..4febdf87cde 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -1260,6 +1260,43 @@ static int expo_scene_obj_type_name(struct unit_test_state *uts) } BOOTSTD_TEST(expo_scene_obj_type_name, 0); +/* Test scene_chklog() */ +static int expo_scene_chklog(struct unit_test_state *uts) +{ + /* Without filter, all objects should be logged */ + env_set("expo_log_filter", NULL); + ut_assert(scene_chklog("my-menu")); + ut_assert(scene_chklog("textline")); + + /* With a single filter, only matching objects should be logged */ + env_set("expo_log_filter", "menu"); + ut_assert(scene_chklog("my-menu")); + ut_assert(scene_chklog("menu-item")); + ut_assert(!scene_chklog("textline")); + ut_assert(!scene_chklog("other")); + + /* With comma-separated filters, any match should pass */ + env_set("expo_log_filter", "menu,text"); + ut_assert(scene_chklog("my-menu")); + ut_assert(scene_chklog("textline")); + ut_assert(scene_chklog("textedit")); + ut_assert(!scene_chklog("other")); + ut_assert(!scene_chklog("image")); + + /* Test with three filters */ + env_set("expo_log_filter", "menu,text,img"); + ut_assert(scene_chklog("my-menu")); + ut_assert(scene_chklog("textline")); + ut_assert(scene_chklog("img-logo")); + ut_assert(!scene_chklog("other")); + + /* Clear the filter */ + env_set("expo_log_filter", NULL); + + return 0; +} +BOOTSTD_TEST(expo_scene_chklog, 0); + /* Test scene_find_obj_within() */ static int expo_find_obj_within(struct unit_test_state *uts) { -- 2.43.0