1 // Copyright 2014 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.base; 6 7 import org.chromium.base.annotations.CalledByNative; 8 import org.chromium.build.annotations.MainDex; 9 10 import java.util.Map; 11 12 /** 13 * This class provides JNI-related methods to the native library. 14 */ 15 @MainDex 16 public class JNIUtils { 17 private static final String TAG = "JNIUtils"; 18 private static ClassLoader sJniClassLoader; 19 20 /** 21 * Returns a ClassLoader which can load Java classes from the specified split. 22 * 23 * @param splitName Name of the split, or empty string for the base split. 24 */ 25 @CalledByNative getSplitClassLoader(String splitName)26 private static ClassLoader getSplitClassLoader(String splitName) { 27 if (!splitName.isEmpty()) { 28 boolean isInstalled = BundleUtils.isIsolatedSplitInstalled(splitName); 29 Log.i(TAG, "Init JNI Classloader for %s. isInstalled=%b", splitName, isInstalled); 30 31 if (isInstalled) { 32 return BundleUtils.getOrCreateSplitClassLoader(splitName); 33 } else { 34 // Split was installed by PlayCore in "compat" mode, meaning that our base module's 35 // ClassLoader was patched to add the splits' dex file to it. 36 // This should never happen on Android T+, where PlayCore is configured to fully 37 // install splits from the get-go, but can still sometimes happen if play store 38 // is very out of date. 39 } 40 } 41 return sJniClassLoader != null ? sJniClassLoader : JNIUtils.class.getClassLoader(); 42 } 43 44 /** 45 * Sets the ClassLoader to be used for loading Java classes from native. 46 * 47 * @param classLoader the ClassLoader to use. 48 */ setClassLoader(ClassLoader classLoader)49 public static void setClassLoader(ClassLoader classLoader) { 50 sJniClassLoader = classLoader; 51 } 52 53 /** 54 * Helper to convert from java maps to two arrays for JNI. 55 */ splitMap(Map<K, V> map, K[] outKeys, V[] outValues)56 public static <K, V> void splitMap(Map<K, V> map, K[] outKeys, V[] outValues) { 57 assert map.size() == outKeys.length; 58 assert outValues.length == outKeys.length; 59 60 int i = 0; 61 for (Map.Entry<K, V> entry : map.entrySet()) { 62 outKeys[i] = entry.getKey(); 63 outValues[i] = entry.getValue(); 64 i++; 65 } 66 } 67 } 68