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): if sys.version_info < (3, 8):
abi_flags += 'm' 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 += [ suffixes += [
('.cpython-{0}{1}-x86_64-linux-gnu.so'.format(abi_version, abi_flags), 'rb', 3), ('.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), ('.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'] = self.ModuleDef('importlib._bootstrap', implicit = True)
self.modules['_frozen_importlib_external'] = self.ModuleDef('importlib._bootstrap_external', 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: for moduleName in startupModules:
if moduleName not in self.modules: if moduleName not in self.modules:
self.addModule(moduleName, implicit = True) self.addModule(moduleName, implicit = True)

View File

@ -50,7 +50,7 @@ def flag_resource(id, **values):
bitmask = 0 bitmask = 0
flags = attrib.value.split('|') flags = attrib.value.split('|')
for flag in flags: for flag in flags:
bitmask = values[flag] bitmask |= values[flag]
attrib.compiled_item.prim.int_hexadecimal_value = bitmask attrib.compiled_item.prim.int_hexadecimal_value = bitmask
return compile return compile
@ -168,10 +168,11 @@ ANDROID_ATTRIBUTES = {
'allowSingleTap': bool_resource(0x1010259), 'allowSingleTap': bool_resource(0x1010259),
'allowTaskReparenting': bool_resource(0x1010204), 'allowTaskReparenting': bool_resource(0x1010204),
'alwaysRetainTaskState': bool_resource(0x1010203), 'alwaysRetainTaskState': bool_resource(0x1010203),
'appCategory': enum_resource(0x01010545, "game", "audio", "video", "image", "social", "news", "maps", "productivity", "accessibility"),
'clearTaskOnLaunch': bool_resource(0x1010015), '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), 'debuggable': bool_resource(0x0101000f),
'documentLaunchMode': enum_resource(0x1010445, "none", "intoExisting", "always", "never"), '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), 'enabled': bool_resource(0x101000e),
'excludeFromRecents': bool_resource(0x1010017), 'excludeFromRecents': bool_resource(0x1010017),
'exported': bool_resource(0x1010010), 'exported': bool_resource(0x1010010),
@ -179,6 +180,7 @@ ANDROID_ATTRIBUTES = {
'finishOnTaskLaunch': bool_resource(0x1010014), 'finishOnTaskLaunch': bool_resource(0x1010014),
'fullBackupContent': bool_resource(0x10104eb), 'fullBackupContent': bool_resource(0x10104eb),
'glEsVersion': int_resource(0x1010281), 'glEsVersion': int_resource(0x1010281),
'hardwareAccelerated': bool_resource(0x10102d3),
'hasCode': bool_resource(0x101000c), 'hasCode': bool_resource(0x101000c),
'host': str_resource(0x1010028), 'host': str_resource(0x1010028),
'icon': ref_resource(0x1010002), 'icon': ref_resource(0x1010002),
@ -194,8 +196,9 @@ ANDROID_ATTRIBUTES = {
'name': str_resource(0x1010003), 'name': str_resource(0x1010003),
'noHistory': bool_resource(0x101022d), 'noHistory': bool_resource(0x101022d),
'pathPattern': str_resource(0x101002c), 'pathPattern': str_resource(0x101002c),
'resizeableActivity': bool_resource(0x10104f6), 'preferMinimalPostProcessing': bool_resource(0x101060c),
'required': bool_resource(0x101028e), 'required': bool_resource(0x101028e),
'resizeableActivity': bool_resource(0x10104f6),
'scheme': str_resource(0x1010027), 'scheme': str_resource(0x1010027),
'screenOrientation': enum_resource(0x101001e, 'landscape', 'portrait', 'user', 'behind', 'sensor', 'nosensor', 'sensorLandscape', 'sensorPortrait', 'reverseLandscape', 'reversePortrait', 'fullSensor', 'userLandscape', 'userPortrait', 'fullUser', 'locked'), 'screenOrientation': enum_resource(0x101001e, 'landscape', 'portrait', 'user', 'behind', 'sensor', 'nosensor', 'sensorLandscape', 'sensorPortrait', 'reverseLandscape', 'reversePortrait', 'fullSensor', 'userLandscape', 'userPortrait', 'fullUser', 'locked'),
'stateNotNeeded': bool_resource(0x1010016), 'stateNotNeeded': bool_resource(0x1010016),

View File

@ -188,11 +188,26 @@ FrozenImporter.get_data = get_data
""" """
SITE_PY_ANDROID = """ SITE_PY_ANDROID = """
# Define this first, before we import anything that might import an extension
# module.
import sys, os 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 _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 io import RawIOBase, TextIOWrapper
from android_log import write as android_log_write from android_log import write as android_log_write
@ -242,8 +257,9 @@ class AndroidLogStream:
def writable(self): def writable(self):
return True return True
sys.stdout = AndroidLogStream(2, 'Python') if sys.version_info < (3, 13):
sys.stderr = AndroidLogStream(3, 'Python') sys.stdout = AndroidLogStream(4, 'python.stdout')
sys.stderr = AndroidLogStream(5, 'python.stderr')
# Alter FrozenImporter to give a __file__ property to frozen modules. # Alter FrozenImporter to give a __file__ property to frozen modules.
@ -262,20 +278,6 @@ def get_data(path):
FrozenImporter.find_spec = find_spec FrozenImporter.find_spec = find_spec
FrozenImporter.get_data = get_data 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.application_id = None
self.android_abis = None self.android_abis = None
self.android_debuggable = False self.android_debuggable = False
self.android_app_category = None
self.android_version_code = 1 self.android_version_code = 1
self.android_min_sdk_version = 21 self.android_min_sdk_version = 21
self.android_max_sdk_version = None self.android_max_sdk_version = None
@ -516,6 +519,18 @@ class build_apps(setuptools.Command):
tmp.update(self.package_data_dirs) tmp.update(self.package_data_dirs)
self.package_data_dirs = tmp 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). # Default to all supported ABIs (for the given Android version).
if self.android_max_sdk_version and self.android_max_sdk_version < 21: if self.android_max_sdk_version and self.android_max_sdk_version < 21:
assert self.android_max_sdk_version >= 19, \ assert self.android_max_sdk_version >= 19, \
@ -782,10 +797,29 @@ class build_apps(setuptools.Command):
version = self.distribution.get_version() version = self.distribution.get_version()
classifiers = self.distribution.get_classifiers() classifiers = self.distribution.get_classifiers()
is_game = False # If we have no app category, determine it based on the classifiers.
for classifier in classifiers: category = self.android_app_category
if classifier == 'Topic :: Games/Entertainment' or classifier.startswith('Topic :: Games/Entertainment ::'): if not category:
is_game = True 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 = ET.Element('manifest')
manifest.set('xmlns:android', 'http://schemas.android.com/apk/res/android') 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 = ET.SubElement(manifest, 'application')
application.set('android:label', name) 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:debuggable', ('false', 'true')[self.android_debuggable])
application.set('android:extractNativeLibs', 'true') application.set('android:extractNativeLibs', 'true')
application.set('android:hardwareAccelerated', 'true')
app_icon = self.icon_objects.get('*', self.icon_objects.get(self.macos_main_app)) app_icon = self.icon_objects.get('*', self.icon_objects.get(self.macos_main_app))
if app_icon: if app_icon:
@ -828,9 +866,11 @@ class build_apps(setuptools.Command):
activity = ET.SubElement(application, 'activity') activity = ET.SubElement(application, 'activity')
activity.set('android:name', 'org.panda3d.android.PythonActivity') activity.set('android:name', 'org.panda3d.android.PythonActivity')
activity.set('android:label', appname) activity.set('android:label', appname)
activity.set('android:theme', '@android:style/Theme.NoTitleBar') activity.set('android:theme', '@android:style/Theme.NoTitleBar.Fullscreen')
activity.set('android:configChanges', 'orientation|keyboardHidden') 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:launchMode', 'singleInstance')
activity.set('android:preferMinimalPostProcessing', 'true')
act_icon = self.icon_objects.get(appname) act_icon = self.icon_objects.get(appname)
if act_icon and act_icon is not app_icon: if act_icon and act_icon is not app_icon:

View File

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

View File

@ -467,12 +467,12 @@ config_initialized() {
Notify *ptr = Notify::ptr(); 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; int priority = ANDROID_LOG_UNKNOWN;
if (severity != NS_unspecified) { 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__) #elif defined(__EMSCRIPTEN__)

View File

@ -866,7 +866,7 @@ def MakeInstallerAndroid(version, **kwargs):
shutil.copy(source, target) shutil.copy(source, target)
# Walk through the library dependencies. # 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(): for line in handle.communicate()[0].splitlines():
# The line will look something like: # The line will look something like:
# 0x0000000000000001 (NEEDED) Shared library: [libpanda.so] # 0x0000000000000001 (NEEDED) Shared library: [libpanda.so]

View File

@ -2077,13 +2077,23 @@ def CompileJava(target, src, opts):
if GetHost() == 'android': if GetHost() == 'android':
cmd = "ecj " cmd = "ecj "
else: 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) optlevel = GetOptimizeOption(opts)
if optlevel >= 4: if optlevel >= 4:
cmd += "-debug:none " cmd += "-debug:none "
cmd += "-cp " + GetOutputDir() + "/classes " classpath = BracketNameWithQuotes(SDK["ANDROID_JAR"] + ":" + GetOutputDir() + "/classes")
cmd += "-cp " + classpath + " "
cmd += "-d " + GetOutputDir() + "/classes " cmd += "-d " + GetOutputDir() + "/classes "
cmd += BracketNameWithQuotes(src) cmd += BracketNameWithQuotes(src)
oscmd(cmd) oscmd(cmd)
@ -4945,11 +4955,13 @@ if GetTarget() == 'android':
TargetAdd('org/panda3d/android/NativeIStream.class', opts=OPTS, input='NativeIStream.java') 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/NativeOStream.class', opts=OPTS, input='NativeOStream.java')
TargetAdd('org/panda3d/android/PandaActivity.class', opts=OPTS, input='PandaActivity.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('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/NativeIStream.class')
TargetAdd('classes.dex', input='org/panda3d/android/NativeOStream.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.class')
TargetAdd('classes.dex', input='org/panda3d/android/PandaActivity$1.class')
TargetAdd('classes.dex', input='org/panda3d/android/PythonActivity.class') TargetAdd('classes.dex', input='org/panda3d/android/PythonActivity.class')
TargetAdd('p3android_composite1.obj', opts=OPTS, input='p3android_composite1.cxx') 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) DefSymbol(target_pkg, d, v)
return 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"] prefix = SDK["MACOSX"]
if (os.path.isdir(prefix + "/Library/Frameworks/%s.framework" % framework) or if (os.path.isdir(prefix + "/Library/Frameworks/%s.framework" % framework) or
os.path.isdir(prefix + "/System/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. # We need to redistribute the C++ standard library.
stdlibc = os.path.join(ndk_root, 'sources', 'cxx-stl', 'llvm-libc++') stdlibc = os.path.join(ndk_root, 'sources', 'cxx-stl', 'llvm-libc++')
stl_lib = os.path.join(stdlibc, 'libs', abi, 'libc++_shared.so') 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) CopyFile(os.path.join(GetOutputDir(), 'lib', 'libc++_shared.so'), stl_lib)
# The Android support library polyfills C++ features not available in the # 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('win_') \
or platform.startswith('cygwin_') or platform.startswith('cygwin_')
is_macosx = platform.startswith('macosx_') is_macosx = platform.startswith('macosx_')
is_android = platform.startswith('android_')
# Global filepaths # Global filepaths
panda3d_dir = join(output_dir, "panda3d") panda3d_dir = join(output_dir, "panda3d")
@ -747,6 +748,9 @@ def makewheel(version, output_dir, platform=None):
elif is_macosx: elif is_macosx:
pylib_name = 'libpython{0}.{1}{2}.dylib'.format(sys.version_info[0], sys.version_info[1], suffix) 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) 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: else:
pylib_name = get_config_var('LDLIBRARY') pylib_name = get_config_var('LDLIBRARY')
pylib_arch = get_config_var('MULTIARCH') 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"; << "New native activity started on " << *current_thread << "\n";
// Were we given an optional location to write the stdout/stderr streams? // 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;"); methodID = env->GetMethodID(activity_class, "getIntentOutputUri", "()Ljava/lang/String;");
jstring joutput_uri = (jstring) env->CallObjectMethod(activity->clazz, methodID); jstring joutput_uri = (jstring) env->CallObjectMethod(activity->clazz, methodID);
if (joutput_uri != nullptr) { if (joutput_uri != nullptr) {
@ -92,6 +93,7 @@ void android_main(struct android_app* app) {
dup2(fd, 1); dup2(fd, 1);
dup2(fd, 2); dup2(fd, 2);
owns_stdout = true;
} else { } else {
android_cat.error() android_cat.error()
<< "Failed to open output path " << path << "\n"; << "Failed to open output path " << path << "\n";
@ -109,6 +111,7 @@ void android_main(struct android_app* app) {
<< spec.get_server_and_port() << "\n"; << spec.get_server_and_port() << "\n";
dup2(fd, 1); dup2(fd, 1);
dup2(fd, 2); dup2(fd, 2);
owns_stdout = true;
} else { } else {
android_cat.error() android_cat.error()
<< "Failed to open output socket " << "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 // We still need to keep an event loop going until Android gives us leave
// to end the process. // to end the process.
int looper_id; while (!app->destroyRequested) {
int events; int looper_id;
struct android_poll_source *source; struct android_poll_source *source;
while ((looper_id = ALooper_pollAll(-1, nullptr, &events, (void**)&source)) >= 0) { auto result = ALooper_pollOnce(-1, &looper_id, nullptr, (void **)&source);
// Process this event, but intercept application command events.
if (looper_id == LOOPER_ID_MAIN) { if (looper_id == LOOPER_ID_MAIN) {
int8_t cmd = android_app_read_cmd(app); int8_t cmd = android_app_read_cmd(app);
android_app_pre_exec_cmd(app, cmd); android_app_pre_exec_cmd(app, cmd);
@ -300,8 +302,10 @@ void android_main(struct android_app* app) {
env->ReleaseStringUTFChars(filename, filename_str); env->ReleaseStringUTFChars(filename, filename_str);
} }
close(1); if (owns_stdout) {
close(2); close(1);
close(2);
}
// Detach the thread before exiting. // Detach the thread before exiting.
activity->vm->DetachCurrentThread(); activity->vm->DetachCurrentThread();

View File

@ -8,7 +8,7 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" /> <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" /> <uses-feature android:glEsVersion="0x00020000" android:required="true" />
<application android:label="Panda Viewer" android:hasCode="true" android:debuggable="true"> <application android:label="Panda Viewer" android:hasCode="true" android:debuggable="true">

View File

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

View File

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

View File

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

View File

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

View File

@ -1479,7 +1479,7 @@ assemble_row(TextAssembler::TextRow &row,
PN_stdfloat underscore_start = 0.0f; PN_stdfloat underscore_start = 0.0f;
const TextProperties *underscore_properties = nullptr; const TextProperties *underscore_properties = nullptr;
#ifdef HAVE_HARFBUZZ #if defined(HAVE_HARFBUZZ) && defined(HAVE_FREETYPE)
const ComputedProperties *prev_cprops = nullptr; const ComputedProperties *prev_cprops = nullptr;
hb_buffer_t *harfbuff = nullptr; hb_buffer_t *harfbuff = nullptr;
#endif #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()); 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 (tch._cprops != prev_cprops || graphic != nullptr) {
if (harfbuff != nullptr && hb_buffer_get_length(harfbuff) > 0) { if (harfbuff != nullptr && hb_buffer_get_length(harfbuff) > 0) {
// Shape the buffer accumulated so far. // 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) { if (harfbuff != nullptr && hb_buffer_get_length(harfbuff) > 0) {
shape_buffer(harfbuff, placed_glyphs, xpos, prev_cprops->_properties); 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, shape_buffer(hb_buffer_t *buf, PlacedGlyphs &placed_glyphs, PN_stdfloat &xpos,
const TextProperties &properties) { 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 // If we did not specify a text direction, harfbuzz will guess it based on
// the script we are using. // the script we are using.
hb_direction_t direction = HB_DIRECTION_INVALID; 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"; std::string dtool_name = std::string(libdir) + "/libp3dtool.so";
ExecutionEnvironment::set_dtool_name(dtool_name); ExecutionEnvironment::set_dtool_name(dtool_name);
android_cat.info() << "Path to dtool: " << dtool_name << "\n"; android_cat.info() << "Path to dtool: " << dtool_name << "\n";
env->ReleaseStringUTFChars(libdir_jstr, libdir);
} }
// Get the path to the APK. // Get the path to the APK.
@ -184,6 +182,7 @@ void android_main(struct android_app *app) {
// Map the blob to memory // Map the blob to memory
void *blob = map_blob(lib_path, (off_t)blobinfo.blob_offset, (size_t)blobinfo.blob_size); 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(blob != NULL);
assert(blobinfo.num_pointers <= MAX_NUM_POINTERS); assert(blobinfo.num_pointers <= MAX_NUM_POINTERS);
@ -242,14 +241,16 @@ void android_main(struct android_app *app) {
preconfig.utf8_mode = 1; preconfig.utf8_mode = 1;
PyStatus status = Py_PreInitialize(&preconfig); PyStatus status = Py_PreInitialize(&preconfig);
if (PyStatus_Exception(status)) { if (PyStatus_Exception(status)) {
Py_ExitStatusException(status); env->ReleaseStringUTFChars(libdir_jstr, libdir);
return; Py_ExitStatusException(status);
return;
} }
// Register the android_log module. // Register the android_log module.
if (PyImport_AppendInittab("android_log", &PyInit_android_log) < 0) { if (PyImport_AppendInittab("android_log", &PyInit_android_log) < 0) {
android_cat.error() android_cat.error()
<< "Failed to register android_log module.\n"; << "Failed to register android_log module.\n";
env->ReleaseStringUTFChars(libdir_jstr, libdir);
return; return;
} }
@ -259,8 +260,8 @@ void android_main(struct android_app *app) {
config.buffered_stdio = 0; config.buffered_stdio = 0;
config.configure_c_stdio = 0; config.configure_c_stdio = 0;
config.write_bytecode = 0; config.write_bytecode = 0;
PyConfig_SetBytesString(&config, &config.executable, lib_path); PyConfig_SetBytesString(&config, &config.platlibdir, libdir);
env->ReleaseStringUTFChars(lib_path_jstr, lib_path); env->ReleaseStringUTFChars(libdir_jstr, libdir);
status = Py_InitializeFromConfig(&config); status = Py_InitializeFromConfig(&config);
PyConfig_Clear(&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 // We still need to keep an event loop going until Android gives us leave
// to end the process. // to end the process.
int looper_id; while (!app->destroyRequested) {
int events; int looper_id;
struct android_poll_source *source; struct android_poll_source *source;
while ((looper_id = ALooper_pollAll(-1, nullptr, &events, (void**)&source)) >= 0) { auto result = ALooper_pollOnce(-1, &looper_id, nullptr, (void **)&source);
// Process this event, but intercept application command events.
if (looper_id == LOOPER_ID_MAIN) { if (looper_id == LOOPER_ID_MAIN) {
int8_t cmd = android_app_read_cmd(app); int8_t cmd = android_app_read_cmd(app);
android_app_pre_exec_cmd(app, cmd); android_app_pre_exec_cmd(app, cmd);
@ -332,4 +332,6 @@ void android_main(struct android_app *app) {
// Detach the thread before exiting. // Detach the thread before exiting.
activity->vm->DetachCurrentThread(); activity->vm->DetachCurrentThread();
_exit(0);
} }