diff --git a/Python/sysmodule.c b/Python/sysmodule.c --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -22,16 +22,20 @@ Data members: #include "osdefs.h" #include #ifdef MS_WINDOWS #define WIN32_LEAN_AND_MEAN #include #endif /* MS_WINDOWS */ +#ifdef __ANDROID__ +#include +#endif + #ifdef MS_COREDLL extern void *PyWin_DLLhModule; /* A string loaded from the DLL at startup: */ extern const char *PyWin_DLLVersionString; #endif #ifdef HAVE_LANGINFO_H #include @@ -1344,16 +1348,85 @@ sys_is_finalizing(PyObject* self, PyObje { return PyBool_FromLong(_Py_Finalizing != NULL); } PyDoc_STRVAR(is_finalizing_doc, "is_finalizing()\n\ Return True if Python is exiting."); +#ifdef __ANDROID__ + +static PyObject * +_Py_property_get(const char* name, char format) +{ + char buf[PROP_VALUE_MAX]; + int len; + + len = __system_property_get(name, buf); + + if (len == 0) + { + Py_RETURN_NONE; + } + + switch (format) + { + case 'u': + return PyUnicode_FromString(buf); + case 'l': + return PyLong_FromString(buf, NULL, 10); + default: + PyErr_Format(PyExc_ValueError, + "property value format '%c' unsupported", format); + return NULL; + } +} + +static PyObject * +sys_getandroidversion(PyObject* self) +{ + PyObject *version, *sdk, *codename, *incremental, *boardname, *abi, *ret; + version = _Py_property_get("ro.build.version.release", 'u'); + sdk = _Py_property_get("ro.build.version.sdk", 'l'); + codename = _Py_property_get("ro.build.version.codename", 'u'); + incremental = _Py_property_get("ro.build.version.incremental", 'u'); + boardname = _Py_property_get("ro.product.board", 'u'); + abi = _Py_property_get("ro.product.cpu.abi", 'u'); + + ret = Py_BuildValue("(OO(OO)(OO))", + version, sdk, codename, incremental, boardname, abi); + Py_DECREF(version); + Py_DECREF(sdk); + Py_DECREF(codename); + Py_DECREF(incremental); + Py_DECREF(boardname); + Py_DECREF(abi); + + return ret; +} + +PyDoc_STRVAR(getandroidversion_doc, +"getandroidversion()\n\ +\n\ +Attempt to get the Android version information.\n\ +\n\ +The function checks Android system properties to retrieve info.\n\ +\n\ +Returns a (version, sdk, versioninfo, hardwareinfo) tuple with\n\ +versioninfo being a (codename, incremental) tuple and hardwareinfo\n\ +being a (boardname, abi) tuple.\n\ +\n\ +Values which cannot be determined are set to the defaults\n\ +given as parameters (which sdk defaults to 0 and others default to '').\n\ +" +); +#endif + + static PyMethodDef sys_methods[] = { /* Might as well keep this in alphabetic order */ {"callstats", (PyCFunction)PyEval_GetCallStats, METH_NOARGS, callstats_doc}, {"_clear_type_cache", sys_clear_type_cache, METH_NOARGS, sys_clear_type_cache__doc__}, {"_current_frames", sys_current_frames, METH_NOARGS, @@ -1429,16 +1502,20 @@ static PyMethodDef sys_methods[] = { {"set_coroutine_wrapper", sys_set_coroutine_wrapper, METH_O, set_coroutine_wrapper_doc}, {"get_coroutine_wrapper", sys_get_coroutine_wrapper, METH_NOARGS, get_coroutine_wrapper_doc}, {"set_asyncgen_hooks", (PyCFunction)sys_set_asyncgen_hooks, METH_VARARGS | METH_KEYWORDS, set_asyncgen_hooks_doc}, {"get_asyncgen_hooks", sys_get_asyncgen_hooks, METH_NOARGS, get_asyncgen_hooks_doc}, +#ifdef __ANDROID__ + {"getandroidversion", sys_getandroidversion, METH_NOARGS, + getandroidversion_doc}, +#endif {NULL, NULL} /* sentinel */ }; static PyObject * list_builtin_module_names(void) { PyObject *list = PyList_New(0); int i;