Browse Source

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

rdb 1 month ago
parent
commit
90ca53ac2d

+ 3 - 3
dtool/src/prc/configPageManager.cxx

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

+ 31 - 18
dtool/src/prc/notify.cxx

@@ -27,6 +27,7 @@
 #endif
 #endif
 
 
 #ifdef ANDROID
 #ifdef ANDROID
+#include <sys/stat.h>
 #include <android/log.h>
 #include <android/log.h>
 #include "androidLogStream.h"
 #include "androidLogStream.h"
 #endif
 #endif
@@ -635,22 +636,7 @@ config_initialized() {
   // notify-output even after the initial import of Panda3D modules.  However,
   // notify-output even after the initial import of Panda3D modules.  However,
   // it cannot be changed after the first time it is set.
   // 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
   // We have no writable filesystem in JavaScript.  Instead, we set up a
   // special stream that logs straight into the Javascript console.
   // special stream that logs straight into the Javascript console.
 
 
@@ -715,11 +701,38 @@ config_initialized() {
         }
         }
 #endif  // BUILD_IPHONE
 #endif  // BUILD_IPHONE
       }
       }
+
 #ifdef ANDROID
 #ifdef ANDROID
+      for (int severity = 0; severity <= NS_fatal; ++severity) {
+        ptr->_log_streams[severity] = ptr->_ostream_ptr;
+      }
+
     } else {
     } 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();
       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
 #endif
     }
     }
   }
   }

+ 1 - 1
dtool/src/prc/pnotify.h

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

+ 5 - 0
panda/src/androiddisplay/androidGraphicsPipe.cxx

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

+ 12 - 9
panda/src/pipeline/threadPosixImpl.cxx

@@ -223,12 +223,15 @@ bind_thread(Thread *thread) {
 
 
 #ifdef ANDROID
 #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() {
 attach_java_vm() {
-  assert(java_vm != nullptr);
+  if (java_vm == nullptr) {
+    return nullptr;
+  }
 
 
   JNIEnv *env;
   JNIEnv *env;
   std::string thread_name = _parent_obj->get_name();
   std::string thread_name = _parent_obj->get_name();
@@ -241,10 +244,10 @@ attach_java_vm() {
       << "Failed to attach Java VM to thread "
       << "Failed to attach Java VM to thread "
       << _parent_obj->get_name() << "!\n";
       << _parent_obj->get_name() << "!\n";
     _jni_env = nullptr;
     _jni_env = nullptr;
-    return false;
+    return nullptr;
   }
   }
   _jni_env = env;
   _jni_env = env;
-  return true;
+  return env;
 }
 }
 
 
 /**
 /**
@@ -317,7 +320,7 @@ root_func(void *data) {
 
 
 #ifdef ANDROID
 #ifdef ANDROID
     // Attach the Java VM to allow calling Java functions in this thread.
     // Attach the Java VM to allow calling Java functions in this thread.
-    self->attach_java_vm();
+    JNIEnv *jni_env = self->attach_java_vm();
 #endif
 #endif
 
 
     self->_parent_obj->thread_main();
     self->_parent_obj->thread_main();
@@ -340,11 +343,11 @@ root_func(void *data) {
 
 
 #ifdef ANDROID
 #ifdef ANDROID
     // We cannot let the thread end without detaching it.
     // We cannot let the thread end without detaching it.
-    if (self->_jni_env != nullptr) {
+    if (jni_env != nullptr) {
       if (java_vm != nullptr) {
       if (java_vm != nullptr) {
         java_vm->DetachCurrentThread();
         java_vm->DetachCurrentThread();
       }
       }
-      self->_jni_env = nullptr;
+      jni_env = nullptr;
     }
     }
 #endif
 #endif
 
 

+ 1 - 1
panda/src/pipeline/threadPosixImpl.h

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