util: Add property_get() fallback for android

Environment variables aren't the easiest thing to use on android.  So
add a fallback to android's property mechanism for os_get_option().

This is slightly complicated by the fact that the assumption that the
return value of os_get_option() need not be freed.

Signed-off-by: Rob Clark <robdclark@chromium.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7763>
This commit is contained in:
Rob Clark 2020-11-24 12:38:47 -08:00 committed by Marge Bot
parent 73c6899285
commit eeecc21d93
1 changed files with 87 additions and 2 deletions

View File

@ -56,6 +56,7 @@
# define LOG_TAG "MESA"
# include <unistd.h>
# include <log/log.h>
# include <cutils/properties.h>
#elif DETECT_OS_LINUX || DETECT_OS_CYGWIN || DETECT_OS_SOLARIS || DETECT_OS_HURD
# include <unistd.h>
#elif DETECT_OS_OPENBSD || DETECT_OS_FREEBSD
@ -121,16 +122,100 @@ os_log_message(const char *message)
#endif
}
#if DETECT_OS_ANDROID
# include <ctype.h>
# include "hash_table.h"
# include "ralloc.h"
# include "simple_mtx.h"
static struct hash_table *options_tbl;
static simple_mtx_t options_tbl_lock = _SIMPLE_MTX_INITIALIZER_NP;
static void
options_tbl_fini(void)
{
_mesa_hash_table_destroy(options_tbl, NULL);
}
/**
* Get an option value from android's property system, as a fallback to
* getenv() (which is generally less useful on android due to processes
* typically being forked from the zygote.
*
* The option name used for getenv is translated into a property name
* by:
*
* 1) convert to lowercase
* 2) replace '_' with '.'
* 3) if necessary, prepend "mesa."
*
* For example:
* - MESA_EXTENSION_OVERRIDE -> mesa.extension.override
* - GALLIUM_HUD -> mesa.gallium.hud
*
* Note that we use a hashtable for two purposes:
* 1) Avoid re-translating the option name on subsequent lookups
* 2) Avoid leaking memory. Because property_get() returns the
* property value into a user allocated buffer, we cannot return
* that directly to the caller, so we need to strdup(). With the
* hashtable, subsquent lookups can return the existing string.
*/
static const char *
os_get_android_option(const char *name)
{
if (!options_tbl) {
options_tbl = _mesa_hash_table_create(NULL, _mesa_hash_string,
_mesa_key_string_equal);
atexit(options_tbl_fini);
}
struct hash_entry *entry = _mesa_hash_table_search(options_tbl, name);
if (entry) {
return entry->data;
}
char value[PROPERTY_VALUE_MAX];
char key[PROPERTY_KEY_MAX];
char *p = key, *end = key + PROPERTY_KEY_MAX;
/* add "mesa." prefix if necessary: */
if (strstr(name, "MESA_") != name)
p += strlcpy(p, "mesa.", end - p);
p += strlcpy(p, name, end - p);
for (int i = 0; key[i]; i++) {
if (key[i] == '_') {
key[i] = '.';
} else {
key[i] = tolower(key[i]);
}
}
const char *opt = NULL;
int len = property_get(key, value, NULL);
if (len > 1) {
opt = ralloc_strdup(options_tbl, value);
}
_mesa_hash_table_insert(options_tbl, name, value);
return opt;
}
#endif
#if !defined(EMBEDDED_DEVICE)
const char *
os_get_option(const char *name)
{
return getenv(name);
const char *opt = getenv(name);
#if DETECT_OS_ANDROID
if (!opt) {
opt = os_get_android_option(name);
}
#endif
return opt;
}
#endif /* !EMBEDDED_DEVICE */
/**
* Return the size of the total physical memory.
* \param size returns the size of the total physical memory