Added information on running valgrind on Android
authorSam Lantinga <slouken@libsdl.org>
Sun, 04 Nov 2012 13:49:32 -0800
changeset 6650d36232135316
parent 6646 dd32cce44d3c
child 6651 17ef8a7cab55
Added information on running valgrind on Android
README.android
src/core/android/SDL_android.cpp
     1.1 --- a/README.android	Sun Nov 04 09:45:18 2012 -0800
     1.2 +++ b/README.android	Sun Nov 04 13:49:32 2012 -0800
     1.3 @@ -48,7 +48,7 @@
     1.4  5. Edit <project>/local.properties to point to the Android SDK directory
     1.5  6. Run 'ant debug' in android/project. This compiles the .java and eventually 
     1.6  creates a .apk with the native code embedded
     1.7 -7. 'ant install' will push the apk to the device or emulator (if connected)
     1.8 +7. 'ant debug install' will push the apk to the device or emulator (if connected)
     1.9  
    1.10  Here's an explanation of the files in the Android project, so you can customize them:
    1.11  
    1.12 @@ -276,6 +276,50 @@
    1.13  
    1.14  
    1.15  ================================================================================
    1.16 + Memory debugging
    1.17 +================================================================================
    1.18 +
    1.19 +The best (and slowest) way to debug memory issues on Android is valgrind.
    1.20 +Valgrind has support for Android out of the box, just grab code using:
    1.21 +	svn co svn://svn.valgrind.org/valgrind/trunk valgrind
    1.22 +... and follow the instructions in the file README.android to build it.
    1.23 +
    1.24 +One thing I needed to do on Mac OS X was change the path to the toolchain,
    1.25 +and add ranlib to the environment variables:
    1.26 +export RANLIB=$NDKROOT/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-ranlib
    1.27 +
    1.28 +Once valgrind is built, you can create a wrapper script to launch your
    1.29 +application with it, changing org.libsdl.app to your package identifier:
    1.30 +--- start_valgrind_app -------------------
    1.31 +#!/system/bin/sh
    1.32 +export TMPDIR=/data/data/org.libsdl.app
    1.33 +exec /data/local/Inst/bin/valgrind --log-file=/sdcard/valgrind.log --error-limit=no $*
    1.34 +------------------------------------------
    1.35 +
    1.36 +Then push it to the device:
    1.37 +	adb push start_valgrind_app /data/local
    1.38 +
    1.39 +and make it executable:
    1.40 +	adb shell chmod 755 /data/local/start_valgrind_app
    1.41 +
    1.42 +and tell Android to use the script to launch your application:
    1.43 +	adb shell setprop wrap.org.libsdl.app "logwrapper /data/local/start_valgrind_app"
    1.44 +
    1.45 +If the setprop command says "could not set property", it's likely that
    1.46 +your package name is too long and you should make it shorter by changing
    1.47 +AndroidManifest.xml and the path to your class file in android-project/src
    1.48 +
    1.49 +You can then launch your application normally and waaaaaaaiiittt for it.
    1.50 +You can monitor the startup process with the logcat command above, and
    1.51 +when it's done (or even while it's running) you can grab the valgrind
    1.52 +output file:
    1.53 +	adb pull /sdcard/valgrind.log
    1.54 +
    1.55 +When you're done instrumenting with valgrind, you can disable the wrapper:
    1.56 +	adb shell setprop wrap.org.libsdl.app ""
    1.57 +
    1.58 +
    1.59 +================================================================================
    1.60   Known issues
    1.61  ================================================================================
    1.62  
     2.1 --- a/src/core/android/SDL_android.cpp	Sun Nov 04 09:45:18 2012 -0800
     2.2 +++ b/src/core/android/SDL_android.cpp	Sun Nov 04 13:49:32 2012 -0800
     2.3 @@ -21,6 +21,7 @@
     2.4  #include "SDL_config.h"
     2.5  #include "SDL_stdinc.h"
     2.6  #include "SDL_assert.h"
     2.7 +#include "SDL_log.h"
     2.8  
     2.9  #ifdef __ANDROID__
    2.10  
    2.11 @@ -41,6 +42,8 @@
    2.12  #define LOGI(...) do {} while (false)
    2.13  #define LOGE(...) do {} while (false)
    2.14  
    2.15 +/* Uncomment this to log messages entering and exiting methods in this file */
    2.16 +//#define DEBUG_JNI
    2.17  
    2.18  /* Implemented in audio/android/SDL_androidaudio.c */
    2.19  extern void Android_RunAudioThread();
    2.20 @@ -259,8 +262,15 @@
    2.21      }
    2.22  
    2.23  public:
    2.24 -    LocalReferenceHolder() : m_env(NULL) { }
    2.25 +    LocalReferenceHolder(const char *func) : m_env(NULL), m_func(func) {
    2.26 +#ifdef DEBUG_JNI
    2.27 +        SDL_Log("Entering function %s", m_func);
    2.28 +#endif
    2.29 +    }
    2.30      ~LocalReferenceHolder() {
    2.31 +#ifdef DEBUG_JNI
    2.32 +        SDL_Log("Leaving function %s", m_func);
    2.33 +#endif
    2.34          if (m_env) {
    2.35              m_env->PopLocalFrame(NULL);
    2.36              --s_active;
    2.37 @@ -279,6 +289,7 @@
    2.38  
    2.39  protected:
    2.40      JNIEnv *m_env;
    2.41 +    const char *m_func;
    2.42  };
    2.43  int LocalReferenceHolder::s_active;
    2.44  
    2.45 @@ -497,7 +508,7 @@
    2.46  
    2.47  static int Android_JNI_FileOpen(SDL_RWops* ctx)
    2.48  {
    2.49 -    LocalReferenceHolder refs;
    2.50 +    LocalReferenceHolder refs(__FUNCTION__);
    2.51      int result = 0;
    2.52  
    2.53      jmethodID mid;
    2.54 @@ -592,7 +603,7 @@
    2.55  extern "C" int Android_JNI_FileOpen(SDL_RWops* ctx,
    2.56          const char* fileName, const char*)
    2.57  {
    2.58 -    LocalReferenceHolder refs;
    2.59 +    LocalReferenceHolder refs(__FUNCTION__);
    2.60      JNIEnv *mEnv = Android_JNI_GetEnv();
    2.61  
    2.62      if (!refs.init(mEnv)) {
    2.63 @@ -615,7 +626,7 @@
    2.64  extern "C" size_t Android_JNI_FileRead(SDL_RWops* ctx, void* buffer,
    2.65          size_t size, size_t maxnum)
    2.66  {
    2.67 -    LocalReferenceHolder refs;
    2.68 +    LocalReferenceHolder refs(__FUNCTION__);
    2.69      jlong bytesRemaining = (jlong) (size * maxnum);
    2.70      jlong bytesMax = (jlong) (ctx->hidden.androidio.size -  ctx->hidden.androidio.position);
    2.71      int bytesRead = 0;
    2.72 @@ -661,7 +672,7 @@
    2.73  
    2.74  static int Android_JNI_FileClose(SDL_RWops* ctx, bool release)
    2.75  {
    2.76 -    LocalReferenceHolder refs;
    2.77 +    LocalReferenceHolder refs(__FUNCTION__);
    2.78      int result = 0;
    2.79      JNIEnv *mEnv = Android_JNI_GetEnv();
    2.80  
    2.81 @@ -731,7 +742,7 @@
    2.82  
    2.83      Sint64 movement = newPosition - ctx->hidden.androidio.position;
    2.84      if (movement > 0) {
    2.85 -        unsigned char buffer[1024];
    2.86 +        unsigned char buffer[4096];
    2.87  
    2.88          // The easy case where we're seeking forwards
    2.89          while (movement > 0) {
    2.90 @@ -767,7 +778,7 @@
    2.91  // returns a new global reference which needs to be released later
    2.92  static jobject Android_JNI_GetSystemServiceObject(const char* name)
    2.93  {
    2.94 -    LocalReferenceHolder refs;
    2.95 +    LocalReferenceHolder refs(__FUNCTION__);
    2.96      JNIEnv* env = Android_JNI_GetEnv();
    2.97      if (!refs.init(env)) {
    2.98          return NULL;
    2.99 @@ -789,7 +800,7 @@
   2.100  }
   2.101  
   2.102  #define SETUP_CLIPBOARD(error) \
   2.103 -    LocalReferenceHolder refs; \
   2.104 +    LocalReferenceHolder refs(__FUNCTION__); \
   2.105      JNIEnv* env = Android_JNI_GetEnv(); \
   2.106      if (!refs.init(env)) { \
   2.107          return error; \
   2.108 @@ -847,7 +858,7 @@
   2.109  // returns the value in seconds and percent or -1 if not available
   2.110  extern "C" int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seconds, int* percent)
   2.111  {
   2.112 -    LocalReferenceHolder refs;
   2.113 +    LocalReferenceHolder refs(__FUNCTION__);
   2.114      JNIEnv* env = Android_JNI_GetEnv();
   2.115      if (!refs.init(env)) {
   2.116          return -1;
   2.117 @@ -993,7 +1004,7 @@
   2.118  
   2.119  extern "C" void *SDL_AndroidGetActivity()
   2.120  {
   2.121 -    LocalReferenceHolder refs;
   2.122 +    LocalReferenceHolder refs(__FUNCTION__);
   2.123      jmethodID mid;
   2.124  
   2.125      JNIEnv *env = Android_JNI_GetEnv();
   2.126 @@ -1012,7 +1023,7 @@
   2.127      static char *s_AndroidInternalFilesPath = NULL;
   2.128  
   2.129      if (!s_AndroidInternalFilesPath) {
   2.130 -        LocalReferenceHolder refs;
   2.131 +        LocalReferenceHolder refs(__FUNCTION__);
   2.132          jmethodID mid;
   2.133          jobject context;
   2.134          jobject fileObject;
   2.135 @@ -1052,7 +1063,7 @@
   2.136  
   2.137  extern "C" int SDL_AndroidGetExternalStorageState()
   2.138  {
   2.139 -    LocalReferenceHolder refs;
   2.140 +    LocalReferenceHolder refs(__FUNCTION__);
   2.141      jmethodID mid;
   2.142      jclass cls;
   2.143      jstring stateString;
   2.144 @@ -1092,7 +1103,7 @@
   2.145      static char *s_AndroidExternalFilesPath = NULL;
   2.146  
   2.147      if (!s_AndroidExternalFilesPath) {
   2.148 -        LocalReferenceHolder refs;
   2.149 +        LocalReferenceHolder refs(__FUNCTION__);
   2.150          jmethodID mid;
   2.151          jobject context;
   2.152          jobject fileObject;