summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorMalcolm Smith <smith@chaquo.com>2024-04-30 14:00:31 (GMT)
committerGitHub <noreply@github.com>2024-04-30 14:00:31 (GMT)
commit3b268f4edc02b22257d745363b5cae199b6e5720 (patch)
tree6a485b90d723817ae9a16b4bad5995f77698a364 /Python
parent11f8348d78c22f85694d7a424541b34d6054a8ee (diff)
downloadcpython-3b268f4edc02b22257d745363b5cae199b6e5720.zip
cpython-3b268f4edc02b22257d745363b5cae199b6e5720.tar.gz
cpython-3b268f4edc02b22257d745363b5cae199b6e5720.tar.bz2
gh-116622: Redirect stdout and stderr to system log when embedded in an Android app (#118063)
Diffstat (limited to 'Python')
-rw-r--r--Python/pylifecycle.c77
-rw-r--r--Python/stdlib_module_names.h1
2 files changed, 78 insertions, 0 deletions
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 0f3ca4a..a672d8c 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -71,6 +71,9 @@ static PyStatus add_main_module(PyInterpreterState *interp);
static PyStatus init_import_site(void);
static PyStatus init_set_builtins_open(void);
static PyStatus init_sys_streams(PyThreadState *tstate);
+#ifdef __ANDROID__
+static PyStatus init_android_streams(PyThreadState *tstate);
+#endif
static void wait_for_thread_shutdown(PyThreadState *tstate);
static void call_ll_exitfuncs(_PyRuntimeState *runtime);
@@ -1223,6 +1226,13 @@ init_interp_main(PyThreadState *tstate)
return status;
}
+#ifdef __ANDROID__
+ status = init_android_streams(tstate);
+ if (_PyStatus_EXCEPTION(status)) {
+ return status;
+ }
+#endif
+
#ifdef Py_DEBUG
run_presite(tstate);
#endif
@@ -2719,6 +2729,73 @@ done:
}
+#ifdef __ANDROID__
+#include <android/log.h>
+
+static PyObject *
+android_log_write_impl(PyObject *self, PyObject *args)
+{
+ int prio = 0;
+ const char *tag = NULL;
+ const char *text = NULL;
+ if (!PyArg_ParseTuple(args, "isy", &prio, &tag, &text)) {
+ return NULL;
+ }
+
+ // Despite its name, this function is part of the public API
+ // (https://developer.android.com/ndk/reference/group/logging).
+ __android_log_write(prio, tag, text);
+ Py_RETURN_NONE;
+}
+
+
+static PyMethodDef android_log_write_method = {
+ "android_log_write", android_log_write_impl, METH_VARARGS
+};
+
+
+static PyStatus
+init_android_streams(PyThreadState *tstate)
+{
+ PyStatus status = _PyStatus_OK();
+ PyObject *_android_support = NULL;
+ PyObject *android_log_write = NULL;
+ PyObject *result = NULL;
+
+ _android_support = PyImport_ImportModule("_android_support");
+ if (_android_support == NULL) {
+ goto error;
+ }
+
+ android_log_write = PyCFunction_New(&android_log_write_method, NULL);
+ if (android_log_write == NULL) {
+ goto error;
+ }
+
+ // These log priorities match those used by Java's System.out and System.err.
+ result = PyObject_CallMethod(
+ _android_support, "init_streams", "Oii",
+ android_log_write, ANDROID_LOG_INFO, ANDROID_LOG_WARN);
+ if (result == NULL) {
+ goto error;
+ }
+
+ goto done;
+
+error:
+ _PyErr_Print(tstate);
+ status = _PyStatus_ERR("failed to initialize Android streams");
+
+done:
+ Py_XDECREF(result);
+ Py_XDECREF(android_log_write);
+ Py_XDECREF(_android_support);
+ return status;
+}
+
+#endif // __ANDROID__
+
+
static void
_Py_FatalError_DumpTracebacks(int fd, PyInterpreterState *interp,
PyThreadState *tstate)
diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h
index 08a66f4..f44abf1 100644
--- a/Python/stdlib_module_names.h
+++ b/Python/stdlib_module_names.h
@@ -5,6 +5,7 @@ static const char* _Py_stdlib_module_names[] = {
"__future__",
"_abc",
"_aix_support",
+"_android_support",
"_ast",
"_asyncio",
"_bisect",