Merge remote-tracking branch 'upstream/master'

This commit is contained in:
John Cote 2024-11-28 22:01:48 -05:00
commit 8a58f7ece3
17 changed files with 162 additions and 76 deletions

View File

@ -925,7 +925,22 @@ class Freezer:
if sys.version_info < (3, 8):
abi_flags += 'm'
if 'linux' in self.platform:
if 'android' in self.platform:
arch = self.platform.split('_', 1)[1]
if arch in ('arm64', 'aarch64'):
suffixes.append(('.cpython-{0}{1}-aarch64-linux-android.so'.format(abi_version, abi_flags), 'rb', 3))
elif arch in ('arm', 'armv7l'):
suffixes.append(('.cpython-{0}{1}-arm-linux-androideabi.so'.format(abi_version, abi_flags), 'rb', 3))
elif arch in ('x86_64', 'amd64'):
suffixes.append(('.cpython-{0}{1}-x86_64-linux-android.so'.format(abi_version, abi_flags), 'rb', 3))
elif arch in ('i386', 'i686'):
suffixes.append(('.cpython-{0}{1}-i686-linux-android.so'.format(abi_version, abi_flags), 'rb', 3))
suffixes += [
('.abi{0}.so'.format(sys.version_info[0]), 'rb', 3),
('.so', 'rb', 3),
]
elif 'linux' in self.platform:
suffixes += [
('.cpython-{0}{1}-x86_64-linux-gnu.so'.format(abi_version, abi_flags), 'rb', 3),
('.cpython-{0}{1}-i686-linux-gnu.so'.format(abi_version, abi_flags), 'rb', 3),
@ -1150,6 +1165,9 @@ class Freezer:
self.modules['_frozen_importlib'] = self.ModuleDef('importlib._bootstrap', implicit = True)
self.modules['_frozen_importlib_external'] = self.ModuleDef('importlib._bootstrap_external', implicit = True)
if self.platform.startswith('android'):
self.modules['_android_support'] = self.ModuleDef('_android_support', implicit = True)
for moduleName in startupModules:
if moduleName not in self.modules:
self.addModule(moduleName, implicit = True)

View File

@ -50,7 +50,7 @@ def flag_resource(id, **values):
bitmask = 0
flags = attrib.value.split('|')
for flag in flags:
bitmask = values[flag]
bitmask |= values[flag]
attrib.compiled_item.prim.int_hexadecimal_value = bitmask
return compile
@ -168,10 +168,11 @@ ANDROID_ATTRIBUTES = {
'allowSingleTap': bool_resource(0x1010259),
'allowTaskReparenting': bool_resource(0x1010204),
'alwaysRetainTaskState': bool_resource(0x1010203),
'appCategory': enum_resource(0x01010545, "game", "audio", "video", "image", "social", "news", "maps", "productivity", "accessibility"),
'clearTaskOnLaunch': bool_resource(0x1010015),
'configChanges': flag_resource(0x0101001f, mcc=0x0001, mnc=0x0002, locale=0x0004, touchscreen=0x0008, keyboard=0x0010, keyboardHidden=0x0020, navigation=0x0040, orientation=0x0080, screenLayout=0x0100, uiMode=0x0200, screenSize=0x0400, smallestScreenSize=0x0800, layoutDirection=0x2000, colorMode=0x4000, grammaticalGender=0x8000, fontScale=0x40000000, fontWeightAdjustment=0x10000000),
'debuggable': bool_resource(0x0101000f),
'documentLaunchMode': enum_resource(0x1010445, "none", "intoExisting", "always", "never"),
'configChanges': flag_resource(0x0101001f, mcc=0x0001, mnc=0x0002, locale=0x0004, touchscreen=0x0008, keyboard=0x0010, keyboardHidden=0x0020, navigation=0x0040, orientation=0x0080, screenLayout=0x0100, uiMode=0x0200, screenSize=0x0400, smallestScreenSize=0x0800, layoutDirection=0x2000, fontScale=0x40000000),
'enabled': bool_resource(0x101000e),
'excludeFromRecents': bool_resource(0x1010017),
'exported': bool_resource(0x1010010),
@ -179,6 +180,7 @@ ANDROID_ATTRIBUTES = {
'finishOnTaskLaunch': bool_resource(0x1010014),
'fullBackupContent': bool_resource(0x10104eb),
'glEsVersion': int_resource(0x1010281),
'hardwareAccelerated': bool_resource(0x10102d3),
'hasCode': bool_resource(0x101000c),
'host': str_resource(0x1010028),
'icon': ref_resource(0x1010002),
@ -194,8 +196,9 @@ ANDROID_ATTRIBUTES = {
'name': str_resource(0x1010003),
'noHistory': bool_resource(0x101022d),
'pathPattern': str_resource(0x101002c),
'resizeableActivity': bool_resource(0x10104f6),
'preferMinimalPostProcessing': bool_resource(0x101060c),
'required': bool_resource(0x101028e),
'resizeableActivity': bool_resource(0x10104f6),
'scheme': str_resource(0x1010027),
'screenOrientation': enum_resource(0x101001e, 'landscape', 'portrait', 'user', 'behind', 'sensor', 'nosensor', 'sensorLandscape', 'sensorPortrait', 'reverseLandscape', 'reversePortrait', 'fullSensor', 'userLandscape', 'userPortrait', 'fullUser', 'locked'),
'stateNotNeeded': bool_resource(0x1010016),

View File

@ -188,11 +188,26 @@ FrozenImporter.get_data = get_data
"""
SITE_PY_ANDROID = """
# Define this first, before we import anything that might import an extension
# module.
import sys, os
from importlib import _bootstrap, _bootstrap_external
class AndroidExtensionFinder:
@classmethod
def find_spec(cls, fullname, path=None, target=None):
soname = 'libpy.' + fullname + '.so'
path = os.path.join(sys.platlibdir, soname)
if os.path.exists(path):
loader = _bootstrap_external.ExtensionFileLoader(fullname, path)
return _bootstrap.ModuleSpec(fullname, loader, origin=path)
sys.meta_path.append(AndroidExtensionFinder)
from _frozen_importlib import _imp, FrozenImporter
from importlib import _bootstrap_external
from importlib.abc import Loader, MetaPathFinder
from importlib.machinery import ModuleSpec
from io import RawIOBase, TextIOWrapper
from android_log import write as android_log_write
@ -242,8 +257,9 @@ class AndroidLogStream:
def writable(self):
return True
sys.stdout = AndroidLogStream(2, 'Python')
sys.stderr = AndroidLogStream(3, 'Python')
if sys.version_info < (3, 13):
sys.stdout = AndroidLogStream(4, 'python.stdout')
sys.stderr = AndroidLogStream(5, 'python.stderr')
# Alter FrozenImporter to give a __file__ property to frozen modules.
@ -262,20 +278,6 @@ def get_data(path):
FrozenImporter.find_spec = find_spec
FrozenImporter.get_data = get_data
class AndroidExtensionFinder(MetaPathFinder):
@classmethod
def find_spec(cls, fullname, path=None, target=None):
soname = 'libpy.' + fullname + '.so'
path = os.path.join(os.path.dirname(sys.executable), soname)
if os.path.exists(path):
loader = _bootstrap_external.ExtensionFileLoader(fullname, path)
return ModuleSpec(fullname, loader, origin=path)
sys.meta_path.append(AndroidExtensionFinder)
"""
@ -294,6 +296,7 @@ class build_apps(setuptools.Command):
self.application_id = None
self.android_abis = None
self.android_debuggable = False
self.android_app_category = None
self.android_version_code = 1
self.android_min_sdk_version = 21
self.android_max_sdk_version = None
@ -516,6 +519,18 @@ class build_apps(setuptools.Command):
tmp.update(self.package_data_dirs)
self.package_data_dirs = tmp
if 'android' in self.platforms:
assert self.application_id, \
'Must have a valid application_id when targeting Android!'
parts = self.application_id.split('.')
assert len(parts) >= 2, \
'application_id must contain at least one \'.\' separator!'
for part in parts:
assert part.isidentifier(), \
'Each part of application_id must be a valid identifier!'
# Default to all supported ABIs (for the given Android version).
if self.android_max_sdk_version and self.android_max_sdk_version < 21:
assert self.android_max_sdk_version >= 19, \
@ -782,10 +797,29 @@ class build_apps(setuptools.Command):
version = self.distribution.get_version()
classifiers = self.distribution.get_classifiers()
is_game = False
for classifier in classifiers:
if classifier == 'Topic :: Games/Entertainment' or classifier.startswith('Topic :: Games/Entertainment ::'):
is_game = True
# If we have no app category, determine it based on the classifiers.
category = self.android_app_category
if not category:
for classifier in classifiers:
classifier = tuple(classifier.split(' :: '))
if len(classifier) < 2 or classifier[0] != 'Topic':
continue
if classifier[:2] == ('Topic', 'Games/Entertainment'):
category = 'game'
break
elif classifier[:3] == ('Topic', 'Multimedia', 'Audio'):
category = 'audio'
elif classifier[:4] == ('Topic', 'Multimedia', 'Graphics', 'Editors'):
category = 'image'
elif classifier[:2] == ('Topic', 'Communications', 'Usenet News'):
category = 'news'
elif classifier[:2] == ('Topic', 'Office/Business'):
category = 'productivity'
elif classifier[:3] == ('Topic', 'Communications', 'Chat'):
category = 'social'
elif classifier[:3] == ('Topic', 'Multimedia', 'Video'):
category = 'video'
manifest = ET.Element('manifest')
manifest.set('xmlns:android', 'http://schemas.android.com/apk/res/android')
@ -816,9 +850,13 @@ class build_apps(setuptools.Command):
application = ET.SubElement(manifest, 'application')
application.set('android:label', name)
application.set('android:isGame', ('false', 'true')[is_game])
if category == 'game':
application.set('android:isGame', 'true')
if category:
application.set('android:appCategory', category)
application.set('android:debuggable', ('false', 'true')[self.android_debuggable])
application.set('android:extractNativeLibs', 'true')
application.set('android:hardwareAccelerated', 'true')
app_icon = self.icon_objects.get('*', self.icon_objects.get(self.macos_main_app))
if app_icon:
@ -828,9 +866,11 @@ class build_apps(setuptools.Command):
activity = ET.SubElement(application, 'activity')
activity.set('android:name', 'org.panda3d.android.PythonActivity')
activity.set('android:label', appname)
activity.set('android:theme', '@android:style/Theme.NoTitleBar')
activity.set('android:configChanges', 'orientation|keyboardHidden')
activity.set('android:theme', '@android:style/Theme.NoTitleBar.Fullscreen')
activity.set('android:alwaysRetainTaskState', 'true')
activity.set('android:configChanges', 'layoutDirection|locale|grammaticalGender|fontScale|fontWeightAdjustment|orientation|uiMode|screenLayout|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation')
activity.set('android:launchMode', 'singleInstance')
activity.set('android:preferMinimalPostProcessing', 'true')
act_icon = self.icon_objects.get(appname)
if act_icon and act_icon is not app_icon:

View File

@ -679,7 +679,7 @@ class ShowBase(DirectObject.DirectObject):
complete.
"""
if Thread.getCurrentThread() != Thread.getMainThread():
if sys.platform != "android" and Thread.getCurrentThread() != Thread.getMainThread():
task = taskMgr.add(self.destroy, extraArgs=[])
task.wait()
return
@ -3439,7 +3439,7 @@ class ShowBase(DirectObject.DirectObject):
This method must be called from the main thread, otherwise an error is
thrown.
"""
if Thread.getCurrentThread() != Thread.getMainThread():
if Thread.getCurrentThread() != Thread.getMainThread() and sys.platform != "android":
self.notify.error("run() must be called from the main thread.")
return

View File

@ -467,12 +467,12 @@ config_initialized() {
Notify *ptr = Notify::ptr();
for (int i = 0; i <= NS_fatal; ++i) {
for (int severity = 0; severity <= NS_fatal; ++severity) {
int priority = ANDROID_LOG_UNKNOWN;
if (severity != NS_unspecified) {
priority = i + 1;
priority = severity + 1;
}
ptr->_log_streams[i] = new AndroidLogStream(priority);
ptr->_log_streams[severity] = new AndroidLogStream(priority);
}
#elif defined(__EMSCRIPTEN__)

View File

@ -866,7 +866,7 @@ def MakeInstallerAndroid(version, **kwargs):
shutil.copy(source, target)
# Walk through the library dependencies.
handle = subprocess.Popen(['readelf', '--dynamic', target], stdout=subprocess.PIPE)
handle = subprocess.Popen(['llvm-readelf', '--dynamic', target], stdout=subprocess.PIPE)
for line in handle.communicate()[0].splitlines():
# The line will look something like:
# 0x0000000000000001 (NEEDED) Shared library: [libpanda.so]

View File

@ -2077,13 +2077,23 @@ def CompileJava(target, src, opts):
if GetHost() == 'android':
cmd = "ecj "
else:
cmd = "javac -bootclasspath " + BracketNameWithQuotes(SDK["ANDROID_JAR"]) + " "
cmd = "javac "
home = os.environ.get('JAVA_HOME')
if home:
javac_path = os.path.join(home, 'bin', 'javac')
if GetHost() == 'windows':
javac_path += '.exe'
if os.path.isfile(javac_path):
cmd = BracketNameWithQuotes(javac_path) + " "
cmd += "-Xlint:deprecation "
optlevel = GetOptimizeOption(opts)
if optlevel >= 4:
cmd += "-debug:none "
cmd += "-cp " + GetOutputDir() + "/classes "
classpath = BracketNameWithQuotes(SDK["ANDROID_JAR"] + ":" + GetOutputDir() + "/classes")
cmd += "-cp " + classpath + " "
cmd += "-d " + GetOutputDir() + "/classes "
cmd += BracketNameWithQuotes(src)
oscmd(cmd)
@ -4945,11 +4955,13 @@ if GetTarget() == 'android':
TargetAdd('org/panda3d/android/NativeIStream.class', opts=OPTS, input='NativeIStream.java')
TargetAdd('org/panda3d/android/NativeOStream.class', opts=OPTS, input='NativeOStream.java')
TargetAdd('org/panda3d/android/PandaActivity.class', opts=OPTS, input='PandaActivity.java')
TargetAdd('org/panda3d/android/PandaActivity$1.class', opts=OPTS+['DEPENDENCYONLY'], input='PandaActivity.java')
TargetAdd('org/panda3d/android/PythonActivity.class', opts=OPTS, input='PythonActivity.java')
TargetAdd('classes.dex', input='org/panda3d/android/NativeIStream.class')
TargetAdd('classes.dex', input='org/panda3d/android/NativeOStream.class')
TargetAdd('classes.dex', input='org/panda3d/android/PandaActivity.class')
TargetAdd('classes.dex', input='org/panda3d/android/PandaActivity$1.class')
TargetAdd('classes.dex', input='org/panda3d/android/PythonActivity.class')
TargetAdd('p3android_composite1.obj', opts=OPTS, input='p3android_composite1.cxx')

View File

@ -1846,7 +1846,7 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None,
DefSymbol(target_pkg, d, v)
return
elif not custom_loc and GetHost() == "darwin" and framework is not None:
elif not custom_loc and GetHost() == "darwin" and GetTarget() == "darwin" and framework is not None:
prefix = SDK["MACOSX"]
if (os.path.isdir(prefix + "/Library/Frameworks/%s.framework" % framework) or
os.path.isdir(prefix + "/System/Library/Frameworks/%s.framework" % framework) or
@ -2622,6 +2622,8 @@ def SdkLocateAndroid():
# We need to redistribute the C++ standard library.
stdlibc = os.path.join(ndk_root, 'sources', 'cxx-stl', 'llvm-libc++')
stl_lib = os.path.join(stdlibc, 'libs', abi, 'libc++_shared.so')
if not os.path.isfile(stl_lib):
stl_lib = os.path.join(prebuilt_dir, 'sysroot', 'usr', 'lib', ANDROID_TRIPLE.rstrip('0123456789'), 'libc++_shared.so')
CopyFile(os.path.join(GetOutputDir(), 'lib', 'libc++_shared.so'), stl_lib)
# The Android support library polyfills C++ features not available in the

View File

@ -677,6 +677,7 @@ def makewheel(version, output_dir, platform=None):
or platform.startswith('win_') \
or platform.startswith('cygwin_')
is_macosx = platform.startswith('macosx_')
is_android = platform.startswith('android_')
# Global filepaths
panda3d_dir = join(output_dir, "panda3d")
@ -747,6 +748,9 @@ def makewheel(version, output_dir, platform=None):
elif is_macosx:
pylib_name = 'libpython{0}.{1}{2}.dylib'.format(sys.version_info[0], sys.version_info[1], suffix)
pylib_path = os.path.join(get_config_var('LIBDIR'), pylib_name)
elif is_android and CrossCompiling():
pylib_name = 'libpython{0}.{1}{2}.so'.format(sys.version_info[0], sys.version_info[1], suffix)
pylib_path = os.path.join(GetThirdpartyDir(), 'python', 'lib', pylib_name)
else:
pylib_name = get_config_var('LDLIBRARY')
pylib_arch = get_config_var('MULTIARCH')

View File

@ -75,6 +75,7 @@ void android_main(struct android_app* app) {
<< "New native activity started on " << *current_thread << "\n";
// Were we given an optional location to write the stdout/stderr streams?
bool owns_stdout = false;
methodID = env->GetMethodID(activity_class, "getIntentOutputUri", "()Ljava/lang/String;");
jstring joutput_uri = (jstring) env->CallObjectMethod(activity->clazz, methodID);
if (joutput_uri != nullptr) {
@ -92,6 +93,7 @@ void android_main(struct android_app* app) {
dup2(fd, 1);
dup2(fd, 2);
owns_stdout = true;
} else {
android_cat.error()
<< "Failed to open output path " << path << "\n";
@ -109,6 +111,7 @@ void android_main(struct android_app* app) {
<< spec.get_server_and_port() << "\n";
dup2(fd, 1);
dup2(fd, 2);
owns_stdout = true;
} else {
android_cat.error()
<< "Failed to open output socket "
@ -267,11 +270,10 @@ void android_main(struct android_app* app) {
// We still need to keep an event loop going until Android gives us leave
// to end the process.
int looper_id;
int events;
struct android_poll_source *source;
while ((looper_id = ALooper_pollAll(-1, nullptr, &events, (void**)&source)) >= 0) {
// Process this event, but intercept application command events.
while (!app->destroyRequested) {
int looper_id;
struct android_poll_source *source;
auto result = ALooper_pollOnce(-1, &looper_id, nullptr, (void **)&source);
if (looper_id == LOOPER_ID_MAIN) {
int8_t cmd = android_app_read_cmd(app);
android_app_pre_exec_cmd(app, cmd);
@ -300,8 +302,10 @@ void android_main(struct android_app* app) {
env->ReleaseStringUTFChars(filename, filename_str);
}
close(1);
close(2);
if (owns_stdout) {
close(1);
close(2);
}
// Detach the thread before exiting.
activity->vm->DetachCurrentThread();

View File

@ -8,7 +8,7 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-sdk android:minSdkVersion="21" />
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" />
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<application android:label="Panda Viewer" android:hasCode="true" android:debuggable="true">

View File

@ -181,16 +181,14 @@ process_events() {
GraphicsWindow::process_events();
// Read all pending events.
int looper_id;
int events;
struct android_poll_source* source;
struct android_poll_source *source;
// Loop until all events are read.
while ((looper_id = ALooper_pollAll(0, nullptr, &events, (void**)&source)) >= 0) {
// Process this event.
if (source != nullptr) {
source->process(_app, source);
}
auto result = ALooper_pollOnce(0, nullptr, nullptr, (void **)&source);
nassertv(result != ALOOPER_POLL_ERROR);
// Process this event.
if (source != nullptr) {
source->process(_app, source);
}
}
@ -437,14 +435,15 @@ ns_handle_command(int32_t command) {
case APP_CMD_WINDOW_RESIZED:
properties.set_size(ANativeWindow_getWidth(_app->window),
ANativeWindow_getHeight(_app->window));
system_changed_properties(properties);
break;
case APP_CMD_WINDOW_REDRAW_NEEDED:
break;
case APP_CMD_CONTENT_RECT_CHANGED:
properties.set_origin(_app->contentRect.left, _app->contentRect.top);
/*properties.set_origin(_app->contentRect.left, _app->contentRect.top);
properties.set_size(_app->contentRect.right - _app->contentRect.left,
_app->contentRect.bottom - _app->contentRect.top);
system_changed_properties(properties);
system_changed_properties(properties);*/
break;
case APP_CMD_GAINED_FOCUS:
properties.set_foreground(true);

View File

@ -204,6 +204,8 @@ close_framework() {
_event_handler.remove_all_hooks();
_task_mgr.cleanup();
_is_open = false;
_made_default_pipe = false;
_default_pipe.clear();

View File

@ -1653,11 +1653,11 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
(!cp_errchk_parameter_uniform(p))) {
return false;
}
bool k_prefix = false;
//bool k_prefix = false;
// solve backward compatibility issue
if (pieces[0] == "k") {
k_prefix = true;
//k_prefix = true;
basename = basename.substr(2);
}

View File

@ -19,7 +19,7 @@ ThreadPosixImpl(Thread *parent_obj) :
_parent_obj(parent_obj)
{
_joinable = false;
_detached = false;
_detached = true;
_status = S_new;
#ifdef ANDROID
_jni_env = nullptr;

View File

@ -1479,7 +1479,7 @@ assemble_row(TextAssembler::TextRow &row,
PN_stdfloat underscore_start = 0.0f;
const TextProperties *underscore_properties = nullptr;
#ifdef HAVE_HARFBUZZ
#if defined(HAVE_HARFBUZZ) && defined(HAVE_FREETYPE)
const ComputedProperties *prev_cprops = nullptr;
hb_buffer_t *harfbuff = nullptr;
#endif
@ -1525,7 +1525,7 @@ assemble_row(TextAssembler::TextRow &row,
line_height = max(line_height, font->get_line_height() * properties->get_glyph_scale() * properties->get_text_scale());
}
#ifdef HAVE_HARFBUZZ
#if defined(HAVE_HARFBUZZ) && defined(HAVE_FREETYPE)
if (tch._cprops != prev_cprops || graphic != nullptr) {
if (harfbuff != nullptr && hb_buffer_get_length(harfbuff) > 0) {
// Shape the buffer accumulated so far.
@ -1760,7 +1760,7 @@ assemble_row(TextAssembler::TextRow &row,
}
}
#ifdef HAVE_HARFBUZZ
#if defined(HAVE_HARFBUZZ) && defined(HAVE_FREETYPE)
if (harfbuff != nullptr && hb_buffer_get_length(harfbuff) > 0) {
shape_buffer(harfbuff, placed_glyphs, xpos, prev_cprops->_properties);
}
@ -1797,7 +1797,7 @@ void TextAssembler::
shape_buffer(hb_buffer_t *buf, PlacedGlyphs &placed_glyphs, PN_stdfloat &xpos,
const TextProperties &properties) {
#ifdef HAVE_HARFBUZZ
#if defined(HAVE_HARFBUZZ) && defined(HAVE_FREETYPE)
// If we did not specify a text direction, harfbuzz will guess it based on
// the script we are using.
hb_direction_t direction = HB_DIRECTION_INVALID;

View File

@ -161,8 +161,6 @@ void android_main(struct android_app *app) {
std::string dtool_name = std::string(libdir) + "/libp3dtool.so";
ExecutionEnvironment::set_dtool_name(dtool_name);
android_cat.info() << "Path to dtool: " << dtool_name << "\n";
env->ReleaseStringUTFChars(libdir_jstr, libdir);
}
// Get the path to the APK.
@ -184,6 +182,7 @@ void android_main(struct android_app *app) {
// Map the blob to memory
void *blob = map_blob(lib_path, (off_t)blobinfo.blob_offset, (size_t)blobinfo.blob_size);
env->ReleaseStringUTFChars(lib_path_jstr, lib_path);
assert(blob != NULL);
assert(blobinfo.num_pointers <= MAX_NUM_POINTERS);
@ -242,14 +241,16 @@ void android_main(struct android_app *app) {
preconfig.utf8_mode = 1;
PyStatus status = Py_PreInitialize(&preconfig);
if (PyStatus_Exception(status)) {
Py_ExitStatusException(status);
return;
env->ReleaseStringUTFChars(libdir_jstr, libdir);
Py_ExitStatusException(status);
return;
}
// Register the android_log module.
if (PyImport_AppendInittab("android_log", &PyInit_android_log) < 0) {
android_cat.error()
<< "Failed to register android_log module.\n";
env->ReleaseStringUTFChars(libdir_jstr, libdir);
return;
}
@ -259,8 +260,8 @@ void android_main(struct android_app *app) {
config.buffered_stdio = 0;
config.configure_c_stdio = 0;
config.write_bytecode = 0;
PyConfig_SetBytesString(&config, &config.executable, lib_path);
env->ReleaseStringUTFChars(lib_path_jstr, lib_path);
PyConfig_SetBytesString(&config, &config.platlibdir, libdir);
env->ReleaseStringUTFChars(libdir_jstr, libdir);
status = Py_InitializeFromConfig(&config);
PyConfig_Clear(&config);
@ -297,11 +298,10 @@ void android_main(struct android_app *app) {
// We still need to keep an event loop going until Android gives us leave
// to end the process.
int looper_id;
int events;
struct android_poll_source *source;
while ((looper_id = ALooper_pollAll(-1, nullptr, &events, (void**)&source)) >= 0) {
// Process this event, but intercept application command events.
while (!app->destroyRequested) {
int looper_id;
struct android_poll_source *source;
auto result = ALooper_pollOnce(-1, &looper_id, nullptr, (void **)&source);
if (looper_id == LOOPER_ID_MAIN) {
int8_t cmd = android_app_read_cmd(app);
android_app_pre_exec_cmd(app, cmd);
@ -332,4 +332,6 @@ void android_main(struct android_app *app) {
// Detach the thread before exiting.
activity->vm->DetachCurrentThread();
_exit(0);
}