Q: Android NDK crash in CallObjectMethod calling getSystemService This is a follow-up to another question I asked: Android -- get MEID from JNI
I am trying to get the ID of a phone in Android.  I have some JNI code and a simple test app to call the JNI code.  Here is working Java code from my simple test app:
TelephonyManager tm = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
String id = tm.getDeviceId();

The string id is set to the phone ID value that I want.  But I need to get it from JNI, and just using the above code and passing the ID value in is not an acceptable solution.  (This is to make some JNI code somewhat tamper-proof and I shouldn't trust the Java layer to send a correct ID value.)
Here is the JNI code that I have written, with error handling removed so it is easier to follow.  It works until the indicated line, and then the whole app crashes. 
// "env" and "obj" are passed to a JNI function and are used unmodified in this code
// JNIEnv *env, jobject obj

jclass cls_context = NULL;
jclass cls_tm = NULL;
jobject tm = NULL;
jmethodID mid;
jfieldID fid;
jstring jstr;
jsize len_jstr;


cls_context = (*env)->FindClass(env, "android/content/Context");
fid = (*env)->GetStaticFieldID(env, cls_context, "TELEPHONY_SERVICE",
        "Ljava/lang/String;");
jstr = (*env)->GetStaticObjectField(env, cls_context, fid);

mid = (*env)->GetMethodID(env, cls_context, "getSystemService",
        "(Ljava/lang/String;)Ljava/lang/Object;");

tm = (*env)->CallObjectMethod(env, obj, mid, jstr);  // THIS LINE CRASHES

cls_tm = (*env)->FindClass(env, "android/telephony/TelephonyManager");

mid = (*env)->GetMethodID(env, cls_tm, "getDeviceId",
        "()Ljava/lang/String;");

jstr = (*env)->CallObjectMethod(env, tm, mid);

len_jstr = (*env)->GetStringUTFLength(env, jstr);

(*env)->GetStringUTFRegion(env, jstr, 0, len_jstr, buf_devid);

I think the problem is that obj isn't the right thing to pass, but if so I have no idea what is the right thing.  Isn't obj that gets passed to the JNI function the same thing as this in the Java code?
EDIT: Okay, we have figured out that if we add an extra argument of type jobject to the JNI function, and explicitly pass a copy of this in that argument, and then pass that to CallObjectMethod() (the one that crashes in the above code), everything works.  We get our TelephonyManager instance and we can query the Phone ID value.
Using a logging macro, I logged the obj pointer and the passed-in this pointer.  They are similar numbers (addresses close to each other) but not identical.  So I think obj is some sort of object reference from inside the Java VM... it is not actually the same as this.
In a JNI function, the first two arguments are JNIEnv *env and jobject obj.  What is that second one for?  What can I do with it?  Is there any way I can use it to call getSystemService or will I have to pass an extra argument and pass in this?

A: The problem seems to be related to Java inheritance: in Java, you can call this.getSystemService() and it works, even though this is not actually an instance of Context.  When you make the JNI call, the call simply fails.
So our solution was to have our Android app add a .getApplicationContext() method function actually as part of its own class.  This in turn calls the actual getSystemService() and returns the result.
The code didn't change: we are still calling
mid = (*env)->GetMethodID(env, cls_context, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");

but now it works, when there is a .getSystemService() method in the class that is calling our JNI function.  So, the env argument in a JNI call does represent this (it's not identical... I printed the value of this as a pointer, and printed env, and they are not the same but they are definitely related).

A: If you want to call a superclass method on object, you should use CallNonvirtualObjectMethod()
How to call an overriden method in JNI

A: Try this... It works... "context" came from java :)
jclass ctx = env->FindClass("android/content/Context");
jfieldID fid = env->GetStaticFieldID(ctx,"TELEPHONY_SERVICE","Ljava/lang/String;");
jstring str = (jstring) env->GetStaticObjectField(ctx, fid);
jmethodID mid = env->GetMethodID(ctx, "getSystemService","(Ljava/lang/String;)Ljava/lang/Object;");
jobject tm = env->CallObjectMethod(context, mid, str);

jclass ctx_tm = env->FindClass("android/telephony/TelephonyManager");
jmethodID mid_tm = env->GetMethodID(ctx_tm,"getDeviceId","()Ljava/lang/String;");
jstring str_tm = (jstring) env->CallObjectMethod(tm, mid_tm);

strReturn = env->GetStringUTFChars(str_tm, 0);

