1 package com.android.nn.benchmark.core.sl; 2 3 import android.content.Context; 4 import android.util.Log; 5 import com.android.nn.benchmark.core.NNTestBase; 6 import dalvik.system.BaseDexClassLoader; 7 import java.io.BufferedReader; 8 import java.io.File; 9 import java.io.FileNotFoundException; 10 import java.io.FileOutputStream; 11 import java.io.IOException; 12 import java.io.InputStream; 13 import java.io.InputStreamReader; 14 import java.io.OutputStream; 15 import java.util.jar.JarEntry; 16 import java.util.jar.JarFile; 17 import java.util.stream.Collectors; 18 19 /** 20 * Abstracts the initialization required to enable a NNAPI Support Library for a given vendor. 21 **/ 22 public abstract class SupportLibraryDriverHandler { 23 24 static { 25 System.loadLibrary("support_library_jni"); 26 } 27 28 protected static final String TAG = "NN_TESTBASE"; 29 30 private static final String NNAPI_SL_LIBRARIES_LIST_ASSET_PATH = "sl_prebuilt_filelist.txt"; 31 public static final String NNAPI_SL_LIB_NAME = "libnnapi_sl_driver.so"; 32 loadNnApiSlHandle(String nnApiSlPath)33 private static native long loadNnApiSlHandle(String nnApiSlPath); 34 35 // Guarded by this 36 private static long nnapiSlHandle = 0; 37 getOrLoadNnApiSlHandle(Context context, boolean extractNnApiSupportLibrary)38 public synchronized long getOrLoadNnApiSlHandle(Context context, boolean extractNnApiSupportLibrary) 39 throws IOException { 40 if (nnapiSlHandle == 0) { 41 Log.i(TAG, "Initializing NNAPI SL."); 42 43 String nnSupportLibFilePath = null; 44 Log.i(TAG, "Preparing NNAPI SL"); 45 if (extractNnApiSupportLibrary) { 46 nnSupportLibFilePath = extractAllAndGetNnApiSlPath(context, NNAPI_SL_LIB_NAME); 47 } else { 48 nnSupportLibFilePath = getNnApiSlPathFromApkLibraries(context, NNAPI_SL_LIB_NAME); 49 } 50 51 prepareDriver(context, nnSupportLibFilePath); 52 53 if (nnSupportLibFilePath != null) { 54 nnapiSlHandle = loadNnApiSlHandle(nnSupportLibFilePath); 55 if (nnapiSlHandle == 0) { 56 Log.e(TAG, String 57 .format("Unable load NNAPI SL from '%s'.", nnSupportLibFilePath)); 58 } else { 59 Log.i(TAG, String 60 .format("Successfully loaded NNAPI SL from '%s'.", nnSupportLibFilePath)); 61 } 62 } else { 63 Log.e(TAG, String 64 .format("Unable to find NNAPI SL entry point '%s' in embedded libraries path.", 65 NNAPI_SL_LIB_NAME)); 66 } 67 } 68 return nnapiSlHandle; 69 } 70 getInputStreamFromApk(String apkPath, String filePath)71 private static InputStream getInputStreamFromApk(String apkPath, String filePath) throws IOException { 72 Log.i(TAG, String.format("Getting input stream from APK '%s' and file '%s'.", apkPath, filePath)); 73 74 JarFile jarFile = new JarFile(apkPath); 75 JarEntry jarEntry = jarFile.getJarEntry(filePath); 76 return jarFile.getInputStream(jarEntry); 77 } 78 extractAllAndGetNnApiSlPath(Context context, String entryPointName)79 private static String extractAllAndGetNnApiSlPath(Context context, String entryPointName) 80 throws IOException { 81 try { 82 BufferedReader slLibraryListReader 83 = new BufferedReader( 84 new InputStreamReader( 85 context.getAssets().open(NNAPI_SL_LIBRARIES_LIST_ASSET_PATH))); 86 String result = null; 87 final String nnLibTargetFolder = context.getCodeCacheDir().toString(); 88 for (final String libraryFile : slLibraryListReader.lines().collect(Collectors.toList())) { 89 try { 90 boolean copied = extractNnApiSlLibTo(context, libraryFile, nnLibTargetFolder); 91 if (copied && libraryFile.equals(entryPointName)) { 92 result = new File(nnLibTargetFolder, libraryFile).getAbsolutePath(); 93 } 94 } catch (FileNotFoundException unableToExtractFile) { 95 return null; 96 } 97 } 98 return result; 99 } catch (IOException e) { 100 Log.e(TAG, "Unable to find list of SL libraries under assets.", e); 101 throw e; 102 } 103 } 104 extractNnApiSlLibTo(Context context, String libraryFile, String targetFolder)105 protected static boolean extractNnApiSlLibTo(Context context, String libraryFile, String targetFolder) 106 throws IOException { 107 String sourcePath = getNnApiSlPathFromApkLibraries(context, libraryFile); 108 if (sourcePath == null) { 109 Log.w(TAG, String.format("Unable to find SL library '%s' to extract assuming is not part of this chipset distribution.", libraryFile)); 110 return false; 111 } 112 113 String[] apkAndLibraryPaths = sourcePath.split("!"); 114 if (apkAndLibraryPaths.length != 2) { 115 final String errorMsg = String.format("Unable to extract %s.", sourcePath); 116 Log.e(TAG, errorMsg); 117 throw new FileNotFoundException(errorMsg); 118 } 119 120 File targetPath = new File(targetFolder, libraryFile); 121 try(InputStream in = getInputStreamFromApk(apkAndLibraryPaths[0], 122 // Removing leading '/' 123 apkAndLibraryPaths[1].substring(1)); 124 OutputStream out = new FileOutputStream(targetPath) 125 ) { 126 NNTestBase.copyFull(in, out); 127 } 128 129 Log.i(TAG, String.format("Copied '%s' to '%s'.", sourcePath, targetPath)); 130 131 return true; 132 } 133 getNnApiSlPathFromApkLibraries(Context context, String resourceName)134 private static String getNnApiSlPathFromApkLibraries(Context context, String resourceName) { 135 BaseDexClassLoader dexClassLoader = (BaseDexClassLoader) context.getClassLoader(); 136 // Removing the "lib" prefix and ".so" suffix. 137 String libShortName = resourceName.substring(3, resourceName.length() - 3); 138 String result = dexClassLoader.findLibrary(libShortName); 139 if (result != null) { 140 return result; 141 } 142 return dexClassLoader.findLibrary(resourceName); 143 } 144 145 // Vendor-specifi preparation steps prepareDriver(Context context, String nnSupportLibFilePath)146 protected abstract void prepareDriver(Context context, String nnSupportLibFilePath) throws IOException; 147 } 148