Native plugin JNI issue when Multithreaded Rendering enabled

Hi,
I come to make a post to ask for your help after 2 days’ trouble shooting.

My app would run in Android. I have a native plugin (attached). in C# script, I call functions with GL.IssuePluginEvent, and I also use DLL import some of it’s functions. And this plugin also do some JNI calls to android java libs like below:

SurfaceTexture::SurfaceTexture( JNIEnv * jni_ ) :
textureId( 0 ),
javaObject( NULL ),
jni( NULL ),
nanoTimeStamp( 0 ),
updateTexImageMethodId( NULL ),
getTimestampMethodId( NULL ),
setDefaultBufferSizeMethodId( NULL ),
setNotifyFrameAvailableMethodId( NULL )
{
static const char * className = “android/graphics/SurfaceTexture”; /// I would change this class later.
const jclass surfaceTextureClass = jni->FindClass(className);
if ( surfaceTextureClass == 0 ) {
FAIL( “FindClass( %s ) failed”, className );
}

you can see that the android class “android/graphics/SurfaceTexture” is the one to be load by JNI.

So the C# call the native plugin, and the native plugin can call java, and it also works well even when “Multithreaded Rendering” is enabled.

However, when I tried to load a customized java lib in this Native plugin (means, in plugin I do the call to a jar lib I write by myself, and put it to the Asset/Plugin/Android directory), issue happens when Multithreaded Rendering is enabled, the error is “FindClass xxx failed”. And the issue would not happen when Multithreaded Rendering is not enabled. I really have not idea why this happen.

So I got result, when Multithreaded Rendering is enabled, the native plugin can only call the System librarys (the above java class is a standard android class), not cannot call user’s customized java lib. is that right ? Can you share more about Multithreaded Rendering in Unity? In which level does the multi threads exist

Could you help on this, thanks a lot.

2681322–189479–Src.rar (7.66 KB)

the sample code in C# calling the plugin is as below:

class Test : MonoBehaviour
{
#if (UNITY_ANDROID && !UNITY_EDITOR)
[DllImport(“OculusMediaSurface”)]
private static extern void OVR_Media_Surface_Init();

[DllImport(“OculusMediaSurface”)]
protected static extern IntPtr OVR_Media_Surface(IntPtr surfaceTexId, int surfaceWidth, int surfaceHeight, int screenWidth, int screenHeight);

[DllImport(“OculusMediaSurface”)]
private static extern void OVR_Media_Surface_SetEventBase(int eventBase);

#endif

public void Awake()
{
#if UNITY_ANDROID && !UNITY_EDITOR
OVR_Media_Surface_Init();
IssuePluginEvent(MediaSurfaceEventType.Initialize);
#endif
}
private static void IssuePluginEvent(MediaSurfaceEventType eventType)
{
GL.IssuePluginEvent((int)eventType + EventBase);
}
private enum MediaSurfaceEventType
{
Initialize = 0,
Shutdown = 1,
Check = 2, // just trigger surfaceTexture.update (for onFrameAvailable) without actual texture update
Update = 3, // trigger surfaceTexture.update and update texture
SkipFirstFrame = 4,
Max_EventType
};
///


/// The start of the numeric range used by event IDs.
///

///
/// If multiple native rundering plugins are in use, the Oculus Media Surface plugin’s event IDs
/// can be re-mapped to avoid conflicts.
///
/// Set this value so that it is higher than the highest event ID number used by your plugin.
/// Oculus Media Surface plugin event IDs start at eventBase and end at eventBase plus the highest
/// value in MediaSurfaceEventType.
///
public static int EventBase
{
get { return mEventBase; }
set
{
mEventBase = value;
#if (UNITY_ANDROID && !UNITY_EDITOR)
OVR_Media_Surface_SetEventBase(mEventBase);
#endif
}
}
private static int mEventBase = 0;
}

Not that I’m completely sure of this, but perhaps you need to attach your jni env pointer to the current thread before using it to find classes.

yes, the jni env pointer is attached to the thread already before the call. it works well when Multithreaded Rendering is enabled.

This might be helpful.