aboutsummaryrefslogtreecommitdiff
path: root/java/org/brotli/wrapper/android/JniHelper.java
blob: 4ec9fe57dd796d6c29d00c0014036421dae85a47 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package org.brotli.wrapper.android;

import android.content.Context;
import android.os.Build;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.ZipFile;

public class JniHelper {

  // Should be set on application start.
  static Context context = null;

  private static final String LIB_NAME = "native";

  private static void tryInitialize() {
    try {
      System.loadLibrary(LIB_NAME);
    } catch (UnsatisfiedLinkError e) {
      if (context == null) {
        throw e;
      }
      int sdk = Build.VERSION.SDK_INT;
      boolean tryFallback =
          (sdk >= Build.VERSION_CODES.JELLY_BEAN) && (sdk <= Build.VERSION_CODES.KITKAT);
      if (!tryFallback) {
        throw e;
      }
      try {
        String libraryFileName = "lib" + LIB_NAME + ".so";
        String libraryFullPath = context.getFilesDir() + File.separator + libraryFileName;
        File file = new File(libraryFullPath);
        if (!file.exists()) {
          String apkPath = context.getApplicationInfo().sourceDir;
          String pathInApk = "lib/" + Build.CPU_ABI + "/lib" + LIB_NAME + ".so";
          unzip(apkPath, pathInApk, libraryFullPath);
        }
        System.load(libraryFullPath);
      } catch (UnsatisfiedLinkError unsatisfiedLinkError) {
        throw unsatisfiedLinkError;
      } catch (Throwable t) {
        UnsatisfiedLinkError unsatisfiedLinkError = new UnsatisfiedLinkError(
            "Exception while extracting native library: " + t.getMessage());
        unsatisfiedLinkError.initCause(t);
        throw unsatisfiedLinkError;
      }
    }
  }

  private static final Object mutex = new Object();
  private static volatile boolean alreadyInitialized;

  public static void ensureInitialized() {
    synchronized (mutex) {
      if (!alreadyInitialized) {
        // If failed, do not retry.
        alreadyInitialized = true;
        tryInitialize();
      }
    }
  }

  private static void unzip(String zipFileName, String entryName, String outputFileName)
      throws IOException {
    ZipFile zipFile = new ZipFile(zipFileName);
    try {
      InputStream input = zipFile.getInputStream(zipFile.getEntry(entryName));
      OutputStream output = new FileOutputStream(outputFileName);
      byte[] data = new byte[16384];
      int len;
      while ((len = input.read(data)) != -1) {
        output.write(data, 0, len);
      }
      output.close();
      input.close();
    } finally {
      zipFile.close();
    }
  }
}