private static void doLoadLibraryBySoName()

in java/com/facebook/soloader/SoLoader.java [1018:1118]


  private static void doLoadLibraryBySoName(
      String soName, int loadFlags, @Nullable StrictMode.ThreadPolicy oldPolicy)
      throws UnsatisfiedLinkError {

    int result = SoSource.LOAD_RESULT_NOT_FOUND;
    sSoSourcesLock.readLock().lock();
    try {
      if (sSoSources == null) {
        Log.e(TAG, "Could not load: " + soName + " because no SO source exists");
        throw new UnsatisfiedLinkError("couldn't find DSO to load: " + soName);
      }
    } finally {
      sSoSourcesLock.readLock().unlock();
    }

    // This way, we set the thread policy only one per loadLibrary no matter how many
    // dependencies we load.  Each call to StrictMode.allowThreadDiskWrites allocates.
    boolean restoreOldPolicy = false;
    if (oldPolicy == null) {
      oldPolicy = StrictMode.allowThreadDiskReads();
      restoreOldPolicy = true;
    }

    if (SYSTRACE_LIBRARY_LOADING) {
      Api18TraceUtils.beginTraceSection("SoLoader.loadLibrary[", soName, "]");
    }

    Throwable error = null;
    try {
      sSoSourcesLock.readLock().lock();
      try {
        for (int i = 0; result == SoSource.LOAD_RESULT_NOT_FOUND && i < sSoSources.length; ++i) {
          SoSource currentSource = sSoSources[i];
          result = currentSource.loadLibrary(soName, loadFlags, oldPolicy);
          if (result == SoSource.LOAD_RESULT_CORRUPTED_LIB_FILE && sBackupSoSources != null) {
            // Let's try from the backup source
            if (Log.isLoggable(TAG, Log.DEBUG)) {
              Log.d(TAG, "Trying backup SoSource for " + soName);
            }
            for (UnpackingSoSource backupSoSource : sBackupSoSources) {
              backupSoSource.prepare(soName);
              int resultFromBackup = backupSoSource.loadLibrary(soName, loadFlags, oldPolicy);
              if (resultFromBackup == SoSource.LOAD_RESULT_LOADED) {
                result = resultFromBackup;
                break;
              }
            }
            break;
          }
        }
      } finally {
        sSoSourcesLock.readLock().unlock();
      }
    } catch (Throwable t) {
      error = t;
    } finally {
      if (SYSTRACE_LIBRARY_LOADING) {
        Api18TraceUtils.endSection();
      }

      if (restoreOldPolicy) {
        StrictMode.setThreadPolicy(oldPolicy);
      }
      if (result == SoSource.LOAD_RESULT_NOT_FOUND
          || result == SoSource.LOAD_RESULT_CORRUPTED_LIB_FILE) {
        StringBuilder sb = new StringBuilder().append("couldn't find DSO to load: ").append(soName);
        if (error != null) {
          String cause = error.getMessage();
          if (cause == null) {
            cause = error.toString();
          }
          sb.append(" caused by: ").append(cause);
          error.printStackTrace();
        } else {
          // load failure wasn't caused by dependent libraries.
          // Print the sources and current native library directory
          sSoSourcesLock.readLock().lock();
          for (int i = 0; i < sSoSources.length; ++i) {
            sb.append("\n\tSoSource ").append(i).append(": ").append(sSoSources[i].toString());
          }
          if (sApplicationSoSource != null) {
            Context updatedContext = sApplicationSoSource.getUpdatedContext();
            File updatedNativeLibDir =
                ApplicationSoSource.getNativeLibDirFromContext(updatedContext);
            sb.append("\n\tNative lib dir: ")
                .append(updatedNativeLibDir.getAbsolutePath())
                .append("\n");
          }
          sSoSourcesLock.readLock().unlock();
        }
        sb.append(" result: ").append(result);
        final String message = sb.toString();
        Log.e(TAG, message);
        UnsatisfiedLinkError err = new UnsatisfiedLinkError(message);
        if (error != null) {
          err.initCause(error);
        }
        throw err;
      }
    }
  }