Android: factorize asset manager code (bug 2131 and 4297)
authorSylvain Becker <sylvain.becker@gmail.com>
Fri, 08 May 2020 11:00:51 +0200
changeset 13798458e052261cb
parent 13797 55ec5ae4aa0b
child 13799 4a352d1323d8
Android: factorize asset manager code (bug 2131 and 4297)
src/core/android/SDL_android.c
     1.1 --- a/src/core/android/SDL_android.c	Mon May 04 02:27:29 2020 -0400
     1.2 +++ b/src/core/android/SDL_android.c	Fri May 08 11:00:51 2020 +0200
     1.3 @@ -356,6 +356,12 @@
     1.4  static SDL_atomic_t bPermissionRequestPending;
     1.5  static SDL_bool bPermissionRequestResult;
     1.6  
     1.7 +/* Android AssetManager */
     1.8 +static void Internal_Android_Create_AssetManager(void);
     1.9 +static void Internal_Android_Destroy_AssetManager(void);
    1.10 +static AAssetManager *asset_manager = NULL;
    1.11 +static jobject javaAssetManagerRef = 0;
    1.12 +
    1.13  /*******************************************************************************
    1.14                   Functions called by JNI
    1.15  *******************************************************************************/
    1.16 @@ -1177,6 +1183,8 @@
    1.17          Android_ResumeSem = NULL;
    1.18      }
    1.19  
    1.20 +    Internal_Android_Destroy_AssetManager();
    1.21 +
    1.22      str = SDL_GetError();
    1.23      if (str && str[0]) {
    1.24          __android_log_print(ANDROID_LOG_ERROR, "SDL", "SDLActivity thread ends (error=%s)", str);
    1.25 @@ -1799,6 +1807,53 @@
    1.26      return SDL_FALSE;
    1.27  }
    1.28  
    1.29 +static void Internal_Android_Create_AssetManager() {
    1.30 +
    1.31 +    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
    1.32 +    JNIEnv *env = Android_JNI_GetEnv();
    1.33 +    jmethodID mid;
    1.34 +    jobject context;
    1.35 +    jobject javaAssetManager;
    1.36 +
    1.37 +    if (!LocalReferenceHolder_Init(&refs, env)) {
    1.38 +        LocalReferenceHolder_Cleanup(&refs);
    1.39 +        return;
    1.40 +    }
    1.41 +
    1.42 +    /* context = SDLActivity.getContext(); */
    1.43 +    context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext);
    1.44 +
    1.45 +    /* javaAssetManager = context.getAssets(); */
    1.46 +    mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
    1.47 +            "getAssets", "()Landroid/content/res/AssetManager;");
    1.48 +    javaAssetManager = (*env)->CallObjectMethod(env, context, mid);
    1.49 +
    1.50 +    /**
    1.51 +     * Given a Dalvik AssetManager object, obtain the corresponding native AAssetManager
    1.52 +     * object.  Note that the caller is responsible for obtaining and holding a VM reference
    1.53 +     * to the jobject to prevent its being garbage collected while the native object is
    1.54 +     * in use.
    1.55 +     */
    1.56 +    javaAssetManagerRef = (*env)->NewGlobalRef(env, javaAssetManager);
    1.57 +    asset_manager = AAssetManager_fromJava(env, javaAssetManagerRef);
    1.58 +
    1.59 +    if (asset_manager == NULL) {
    1.60 +        (*env)->DeleteGlobalRef(env, javaAssetManagerRef);
    1.61 +        Android_JNI_ExceptionOccurred(SDL_TRUE);
    1.62 +    }
    1.63 +
    1.64 +    LocalReferenceHolder_Cleanup(&refs);
    1.65 +}
    1.66 +
    1.67 +static void Internal_Android_Destroy_AssetManager() {
    1.68 +    JNIEnv *env = Android_JNI_GetEnv();
    1.69 +
    1.70 +    if (asset_manager) {
    1.71 +        (*env)->DeleteGlobalRef(env, javaAssetManagerRef);
    1.72 +        asset_manager = NULL;
    1.73 +    }
    1.74 +}
    1.75 +
    1.76  static int Internal_Android_JNI_FileOpen(SDL_RWops *ctx)
    1.77  {
    1.78      struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
    1.79 @@ -2800,50 +2855,32 @@
    1.80  
    1.81  int Android_JNI_GetLocale(char *buf, size_t buflen)
    1.82  {
    1.83 -    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
    1.84 -    JNIEnv* env = Android_JNI_GetEnv();
    1.85 -    int retval = -1;
    1.86 -
    1.87 -    JNIEnv *mEnv = Android_JNI_GetEnv();
    1.88 -    if (!LocalReferenceHolder_Init(&refs, env)) {
    1.89 -        LocalReferenceHolder_Cleanup(&refs);
    1.90 -        return -1;
    1.91 -    }
    1.92 +    AConfiguration *cfg;
    1.93  
    1.94      SDL_assert(buflen > 6);
    1.95  
    1.96 -    jmethodID mid;
    1.97 -    jobject context;
    1.98 -    jobject assetManager;
    1.99 -
   1.100 -    /* context = SDLActivity.getContext(); */
   1.101 -    mid = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
   1.102 -            "getContext","()Landroid/content/Context;");
   1.103 -    context = (*mEnv)->CallStaticObjectMethod(mEnv, mActivityClass, mid);
   1.104 -
   1.105 -    /* assetManager = context.getAssets(); */
   1.106 -    mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, context),
   1.107 -            "getAssets", "()Landroid/content/res/AssetManager;");
   1.108 -    assetManager = (*mEnv)->CallObjectMethod(mEnv, context, mid);
   1.109 -
   1.110 -
   1.111 -    /* API from NDK: android/configuration.h */
   1.112 -    /* API from NDK: android/asset_manager_jni.h */
   1.113 -    AAssetManager* asset_mgr = AAssetManager_fromJava(env, assetManager);
   1.114 -    AConfiguration *cfg = AConfiguration_new();
   1.115 -
   1.116 -    if (asset_mgr && cfg)
   1.117 +    if (asset_manager == NULL) {
   1.118 +        Internal_Android_Create_AssetManager();
   1.119 +    }
   1.120 +
   1.121 +    if (asset_manager == NULL) {
   1.122 +        return -1;
   1.123 +    }
   1.124 +
   1.125 +    cfg = AConfiguration_new();
   1.126 +    if (cfg == NULL) {
   1.127 +        return -1;
   1.128 +    }
   1.129 +
   1.130      {
   1.131          char language[2] = {};
   1.132          char country[2] = {};
   1.133          size_t id = 0;
   1.134  
   1.135 -        AConfiguration_fromAssetManager(cfg, asset_mgr);
   1.136 +        AConfiguration_fromAssetManager(cfg, asset_manager);
   1.137          AConfiguration_getLanguage(cfg, language);
   1.138          AConfiguration_getCountry(cfg, country);
   1.139  
   1.140 -        retval = 0;
   1.141 -
   1.142          /* copy language (not null terminated) */
   1.143          if (language[0]) {
   1.144              buf[id++] = language[0];
   1.145 @@ -2866,12 +2903,9 @@
   1.146          SDL_assert(id <= buflen);
   1.147      }
   1.148  
   1.149 -    if (cfg) {
   1.150 -        AConfiguration_delete(cfg);
   1.151 -    }
   1.152 -
   1.153 -    LocalReferenceHolder_Cleanup(&refs);
   1.154 -    return retval;
   1.155 +    AConfiguration_delete(cfg);
   1.156 +
   1.157 +    return 0;
   1.158  }
   1.159  
   1.160  #endif /* __ANDROID__ */