android: Fixes to allow Panda to run from the adb shell

This commit is contained in:
rdb
2025-11-05 12:50:30 +01:00
parent e9fddf6839
commit 90ca53ac2d
6 changed files with 53 additions and 32 deletions

View File

@@ -97,7 +97,6 @@ reload_implicit_pages() {
}
_implicit_pages.clear();
#ifndef ANDROID
// If we are running inside a deployed application, see if it exposes
// information about how the PRC data should be initialized.
struct BlobInfo {
@@ -129,11 +128,13 @@ reload_implicit_pages() {
// const BlobInfo *blobinfo = (const BlobInfo *)dlsym(RTLD_SELF, "blobinfo");
#elif defined(__EMSCRIPTEN__)
const BlobInfo *blobinfo = nullptr;
#elif defined(ANDROID)
const BlobInfo *blobinfo = nullptr;
#else
const BlobInfo *blobinfo = (const BlobInfo *)dlsym(dlopen(nullptr, RTLD_NOW), "blobinfo");
#endif
if (blobinfo == nullptr) {
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__)
#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(ANDROID)
// Clear the error flag.
dlerror();
#endif
@@ -482,7 +483,6 @@ reload_implicit_pages() {
}
}
}
#endif // ANDROID
if (!_loaded_implicit) {
config_initialized();

View File

@@ -27,6 +27,7 @@
#endif
#ifdef ANDROID
#include <sys/stat.h>
#include <android/log.h>
#include "androidLogStream.h"
#endif
@@ -635,22 +636,7 @@ config_initialized() {
// notify-output even after the initial import of Panda3D modules. However,
// it cannot be changed after the first time it is set.
#if defined(ANDROID)
// Android redirects stdio and stderr to /dev/null,
// but does provide its own logging system. We use a special
// type of stream that redirects it to Android's log system.
Notify *ptr = Notify::ptr();
for (int severity = 0; severity <= NS_fatal; ++severity) {
int priority = ANDROID_LOG_UNKNOWN;
if (severity != NS_unspecified) {
priority = severity + 1;
}
ptr->_log_streams[severity] = new AndroidLogStream(priority);
}
#elif defined(__EMSCRIPTEN__)
#if defined(__EMSCRIPTEN__)
// We have no writable filesystem in JavaScript. Instead, we set up a
// special stream that logs straight into the Javascript console.
@@ -715,11 +701,38 @@ config_initialized() {
}
#endif // BUILD_IPHONE
}
#ifdef ANDROID
for (int severity = 0; severity <= NS_fatal; ++severity) {
ptr->_log_streams[severity] = ptr->_ostream_ptr;
}
} else {
// By default, we always redirect the notify stream to the Android log.
// By default, we always redirect the notify stream to the Android log,
// except if we are running from the adb shell. We decide this based
// on whether stderr is redirected to /dev/null.
Notify *ptr = Notify::ptr();
ptr->set_ostream_ptr(new AndroidLogStream(ANDROID_LOG_INFO), true);
struct stat a, b;
if (fstat(STDERR_FILENO, &a) == 0 && stat("/dev/null", &b) == 0 &&
a.st_dev == b.st_dev && a.st_ino == b.st_ino) {
// Android redirects stdio and stderr to /dev/null,
// but does provide its own logging system. We use a special
// type of stream that redirects it to Android's log system.
for (int severity = 0; severity <= NS_fatal; ++severity) {
int priority = ANDROID_LOG_UNKNOWN;
if (severity != NS_unspecified) {
priority = severity + 1;
}
ptr->_log_streams[severity] = new AndroidLogStream(priority);
}
ptr->set_ostream_ptr(new AndroidLogStream(ANDROID_LOG_INFO), true);
} else {
// Running from the terminal, set all the log streams to point to the
// same output.
for (int severity = 0; severity <= NS_fatal; ++severity) {
ptr->_log_streams[severity] = &cerr;
}
}
#endif
}
}

View File

@@ -102,7 +102,7 @@ private:
Categories _categories;
#if defined(ANDROID)
AndroidLogStream *_log_streams[NS_fatal + 1];
std::ostream *_log_streams[NS_fatal + 1];
#elif defined(__EMSCRIPTEN__)
EmscriptenLogStream *_log_streams[NS_fatal + 1];
#endif

View File

@@ -19,6 +19,8 @@
#include "config_androiddisplay.h"
#include "frameBufferProperties.h"
extern IMPORT_CLASS struct android_app *panda_android_app;
TypeHandle AndroidGraphicsPipe::_type_handle;
/**
@@ -121,6 +123,9 @@ make_output(const std::string &name,
// First thing to try: an eglGraphicsWindow
if (retry == 0) {
if (panda_android_app == nullptr) {
return nullptr;
}
if (((flags&BF_require_parasite)!=0)||
((flags&BF_refuse_window)!=0)||
((flags&BF_resizeable)!=0)||

View File

@@ -223,12 +223,15 @@ bind_thread(Thread *thread) {
#ifdef ANDROID
/**
* Attaches the thread to the Java virtual machine. If this returns true, a
* JNIEnv pointer can be acquired using get_jni_env().
* Attaches the thread to the Java virtual machine. On success, returns a
* JNIEnv pointer; returns nullptr otherwise, in which case the application
* might not be running inside a Java VM.
*/
bool ThreadPosixImpl::
JNIEnv *ThreadPosixImpl::
attach_java_vm() {
assert(java_vm != nullptr);
if (java_vm == nullptr) {
return nullptr;
}
JNIEnv *env;
std::string thread_name = _parent_obj->get_name();
@@ -241,10 +244,10 @@ attach_java_vm() {
<< "Failed to attach Java VM to thread "
<< _parent_obj->get_name() << "!\n";
_jni_env = nullptr;
return false;
return nullptr;
}
_jni_env = env;
return true;
return env;
}
/**
@@ -317,7 +320,7 @@ root_func(void *data) {
#ifdef ANDROID
// Attach the Java VM to allow calling Java functions in this thread.
self->attach_java_vm();
JNIEnv *jni_env = self->attach_java_vm();
#endif
self->_parent_obj->thread_main();
@@ -340,11 +343,11 @@ root_func(void *data) {
#ifdef ANDROID
// We cannot let the thread end without detaching it.
if (self->_jni_env != nullptr) {
if (jni_env != nullptr) {
if (java_vm != nullptr) {
java_vm->DetachCurrentThread();
}
self->_jni_env = nullptr;
jni_env = nullptr;
}
#endif

View File

@@ -59,7 +59,7 @@ public:
#ifdef ANDROID
INLINE JNIEnv *get_jni_env() const;
bool attach_java_vm();
JNIEnv *attach_java_vm();
static void bind_java_thread();
#endif