Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
Added information on running valgrind on Android
Browse files Browse the repository at this point in the history
  • Loading branch information
slouken committed Nov 4, 2012
1 parent 81cc7c6 commit 6585060
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 14 deletions.
46 changes: 45 additions & 1 deletion README.android
Expand Up @@ -48,7 +48,7 @@ If you want to use the Eclipse IDE, skip to the Eclipse section below.
5. Edit <project>/local.properties to point to the Android SDK directory
6. Run 'ant debug' in android/project. This compiles the .java and eventually
creates a .apk with the native code embedded
7. 'ant install' will push the apk to the device or emulator (if connected)
7. 'ant debug install' will push the apk to the device or emulator (if connected)

Here's an explanation of the files in the Android project, so you can customize them:

Expand Down Expand Up @@ -275,6 +275,50 @@ If you need to build without optimization turned on, you can create a file calle
APP_OPTIM := debug


================================================================================
Memory debugging
================================================================================

The best (and slowest) way to debug memory issues on Android is valgrind.
Valgrind has support for Android out of the box, just grab code using:
svn co svn://svn.valgrind.org/valgrind/trunk valgrind
... and follow the instructions in the file README.android to build it.

One thing I needed to do on Mac OS X was change the path to the toolchain,
and add ranlib to the environment variables:
export RANLIB=$NDKROOT/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-ranlib

Once valgrind is built, you can create a wrapper script to launch your
application with it, changing org.libsdl.app to your package identifier:
--- start_valgrind_app -------------------
#!/system/bin/sh
export TMPDIR=/data/data/org.libsdl.app
exec /data/local/Inst/bin/valgrind --log-file=/sdcard/valgrind.log --error-limit=no $*
------------------------------------------

Then push it to the device:
adb push start_valgrind_app /data/local

and make it executable:
adb shell chmod 755 /data/local/start_valgrind_app

and tell Android to use the script to launch your application:
adb shell setprop wrap.org.libsdl.app "logwrapper /data/local/start_valgrind_app"

If the setprop command says "could not set property", it's likely that
your package name is too long and you should make it shorter by changing
AndroidManifest.xml and the path to your class file in android-project/src

You can then launch your application normally and waaaaaaaiiittt for it.
You can monitor the startup process with the logcat command above, and
when it's done (or even while it's running) you can grab the valgrind
output file:
adb pull /sdcard/valgrind.log

When you're done instrumenting with valgrind, you can disable the wrapper:
adb shell setprop wrap.org.libsdl.app ""


================================================================================
Known issues
================================================================================
Expand Down
37 changes: 24 additions & 13 deletions src/core/android/SDL_android.cpp
Expand Up @@ -21,6 +21,7 @@
#include "SDL_config.h"
#include "SDL_stdinc.h"
#include "SDL_assert.h"
#include "SDL_log.h"

#ifdef __ANDROID__

Expand All @@ -41,6 +42,8 @@ extern "C" {
#define LOGI(...) do {} while (false)
#define LOGE(...) do {} while (false)

/* Uncomment this to log messages entering and exiting methods in this file */
//#define DEBUG_JNI

/* Implemented in audio/android/SDL_androidaudio.c */
extern void Android_RunAudioThread();
Expand Down Expand Up @@ -259,8 +262,15 @@ class LocalReferenceHolder
}

public:
LocalReferenceHolder() : m_env(NULL) { }
LocalReferenceHolder(const char *func) : m_env(NULL), m_func(func) {
#ifdef DEBUG_JNI
SDL_Log("Entering function %s", m_func);
#endif
}
~LocalReferenceHolder() {
#ifdef DEBUG_JNI
SDL_Log("Leaving function %s", m_func);
#endif
if (m_env) {
m_env->PopLocalFrame(NULL);
--s_active;
Expand All @@ -279,6 +289,7 @@ class LocalReferenceHolder

protected:
JNIEnv *m_env;
const char *m_func;
};
int LocalReferenceHolder::s_active;

Expand Down Expand Up @@ -497,7 +508,7 @@ static bool Android_JNI_ExceptionOccurred()

static int Android_JNI_FileOpen(SDL_RWops* ctx)
{
LocalReferenceHolder refs;
LocalReferenceHolder refs(__FUNCTION__);
int result = 0;

jmethodID mid;
Expand Down Expand Up @@ -592,7 +603,7 @@ static int Android_JNI_FileOpen(SDL_RWops* ctx)
extern "C" int Android_JNI_FileOpen(SDL_RWops* ctx,
const char* fileName, const char*)
{
LocalReferenceHolder refs;
LocalReferenceHolder refs(__FUNCTION__);
JNIEnv *mEnv = Android_JNI_GetEnv();

if (!refs.init(mEnv)) {
Expand All @@ -615,7 +626,7 @@ extern "C" int Android_JNI_FileOpen(SDL_RWops* ctx,
extern "C" size_t Android_JNI_FileRead(SDL_RWops* ctx, void* buffer,
size_t size, size_t maxnum)
{
LocalReferenceHolder refs;
LocalReferenceHolder refs(__FUNCTION__);
jlong bytesRemaining = (jlong) (size * maxnum);
jlong bytesMax = (jlong) (ctx->hidden.androidio.size - ctx->hidden.androidio.position);
int bytesRead = 0;
Expand Down Expand Up @@ -661,7 +672,7 @@ extern "C" size_t Android_JNI_FileWrite(SDL_RWops* ctx, const void* buffer,

static int Android_JNI_FileClose(SDL_RWops* ctx, bool release)
{
LocalReferenceHolder refs;
LocalReferenceHolder refs(__FUNCTION__);
int result = 0;
JNIEnv *mEnv = Android_JNI_GetEnv();

Expand Down Expand Up @@ -731,7 +742,7 @@ extern "C" Sint64 Android_JNI_FileSeek(SDL_RWops* ctx, Sint64 offset, int whence

Sint64 movement = newPosition - ctx->hidden.androidio.position;
if (movement > 0) {
unsigned char buffer[1024];
unsigned char buffer[4096];

// The easy case where we're seeking forwards
while (movement > 0) {
Expand Down Expand Up @@ -767,7 +778,7 @@ extern "C" int Android_JNI_FileClose(SDL_RWops* ctx)
// returns a new global reference which needs to be released later
static jobject Android_JNI_GetSystemServiceObject(const char* name)
{
LocalReferenceHolder refs;
LocalReferenceHolder refs(__FUNCTION__);
JNIEnv* env = Android_JNI_GetEnv();
if (!refs.init(env)) {
return NULL;
Expand All @@ -789,7 +800,7 @@ static jobject Android_JNI_GetSystemServiceObject(const char* name)
}

#define SETUP_CLIPBOARD(error) \
LocalReferenceHolder refs; \
LocalReferenceHolder refs(__FUNCTION__); \
JNIEnv* env = Android_JNI_GetEnv(); \
if (!refs.init(env)) { \
return error; \
Expand Down Expand Up @@ -847,7 +858,7 @@ extern "C" SDL_bool Android_JNI_HasClipboardText()
// returns the value in seconds and percent or -1 if not available
extern "C" int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seconds, int* percent)
{
LocalReferenceHolder refs;
LocalReferenceHolder refs(__FUNCTION__);
JNIEnv* env = Android_JNI_GetEnv();
if (!refs.init(env)) {
return -1;
Expand Down Expand Up @@ -993,7 +1004,7 @@ extern "C" void *SDL_AndroidGetJNIEnv()

extern "C" void *SDL_AndroidGetActivity()
{
LocalReferenceHolder refs;
LocalReferenceHolder refs(__FUNCTION__);
jmethodID mid;

JNIEnv *env = Android_JNI_GetEnv();
Expand All @@ -1012,7 +1023,7 @@ extern "C" const char * SDL_AndroidGetInternalStoragePath()
static char *s_AndroidInternalFilesPath = NULL;

if (!s_AndroidInternalFilesPath) {
LocalReferenceHolder refs;
LocalReferenceHolder refs(__FUNCTION__);
jmethodID mid;
jobject context;
jobject fileObject;
Expand Down Expand Up @@ -1052,7 +1063,7 @@ extern "C" const char * SDL_AndroidGetInternalStoragePath()

extern "C" int SDL_AndroidGetExternalStorageState()
{
LocalReferenceHolder refs;
LocalReferenceHolder refs(__FUNCTION__);
jmethodID mid;
jclass cls;
jstring stateString;
Expand Down Expand Up @@ -1092,7 +1103,7 @@ extern "C" const char * SDL_AndroidGetExternalStoragePath()
static char *s_AndroidExternalFilesPath = NULL;

if (!s_AndroidExternalFilesPath) {
LocalReferenceHolder refs;
LocalReferenceHolder refs(__FUNCTION__);
jmethodID mid;
jobject context;
jobject fileObject;
Expand Down

0 comments on commit 6585060

Please sign in to comment.