| Index: base/android/java/src/org/chromium/base/library_loader/LibraryLoaderHelper.java
|
| diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoaderHelper.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoaderHelper.java
|
| deleted file mode 100644
|
| index 7dd1a29a0eafe6c4adfc270cb3950843da86f6de..0000000000000000000000000000000000000000
|
| --- a/base/android/java/src/org/chromium/base/library_loader/LibraryLoaderHelper.java
|
| +++ /dev/null
|
| @@ -1,338 +0,0 @@
|
| -// Copyright 2014 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -
|
| -package org.chromium.base.library_loader;
|
| -
|
| -import android.content.Context;
|
| -import android.util.Log;
|
| -
|
| -import java.io.BufferedOutputStream;
|
| -import java.io.Closeable;
|
| -import java.io.File;
|
| -import java.io.FileNotFoundException;
|
| -import java.io.FileOutputStream;
|
| -import java.io.IOException;
|
| -import java.io.InputStream;
|
| -import java.io.OutputStream;
|
| -import java.util.Collection;
|
| -import java.util.Collections;
|
| -import java.util.HashSet;
|
| -import java.util.Map;
|
| -import java.util.Map.Entry;
|
| -import java.util.Set;
|
| -import java.util.zip.ZipEntry;
|
| -import java.util.zip.ZipException;
|
| -import java.util.zip.ZipFile;
|
| -
|
| -/**
|
| - * Class representing an exception which occured during the unpacking process.
|
| - */
|
| -class UnpackingException extends Exception {
|
| - public UnpackingException(String message, Throwable cause) {
|
| - super(message, cause);
|
| - }
|
| -
|
| - public UnpackingException(String message) {
|
| - super(message);
|
| - }
|
| -}
|
| -
|
| -/**
|
| - * The class provides helper functions to extract native libraries from APK,
|
| - * and load libraries from there.
|
| - */
|
| -class LibraryLoaderHelper {
|
| - private static final String TAG = "LibraryLoaderHelper";
|
| -
|
| - // Fallback directories.
|
| - static final String LOAD_FROM_APK_FALLBACK_DIR = "fallback";
|
| -
|
| - private static final int BUFFER_SIZE = 16384;
|
| -
|
| - /**
|
| - * Returns the directory for holding extracted native libraries.
|
| - * It may create the directory if it doesn't exist.
|
| - *
|
| - * @param context The context the code is running.
|
| - * @param dirName The name of the directory containing the libraries.
|
| - * @return The directory file object.
|
| - */
|
| - static File getLibDir(Context context, String dirName) {
|
| - return context.getDir(dirName, Context.MODE_PRIVATE);
|
| - }
|
| -
|
| - /**
|
| - * Delete libraries and their directory synchronously.
|
| - */
|
| - private static void deleteLibrariesSynchronously(Context context, String dirName) {
|
| - File libDir = getLibDir(context, dirName);
|
| - deleteObsoleteLibraries(libDir, Collections.<File>emptyList());
|
| - }
|
| -
|
| - /**
|
| - * Delete libraries and their directory asynchronously.
|
| - * The actual deletion is done in a background thread.
|
| - */
|
| - static void deleteLibrariesAsynchronously(
|
| - final Context context, final String dirName) {
|
| - // Child process should not reach here.
|
| - new Thread() {
|
| - @Override
|
| - public void run() {
|
| - deleteLibrariesSynchronously(context, dirName);
|
| - }
|
| - }.start();
|
| - }
|
| -
|
| - /**
|
| - * Copy a library from a zip file to the application's private directory.
|
| - * This is used as a fallback when we are unable to load the library
|
| - * directly from the APK file (crbug.com/390618).
|
| - *
|
| - * @param context The context the code is running in.
|
| - * @param library Library name.
|
| - * @return name of the fallback copy of the library.
|
| - */
|
| - static String buildFallbackLibrary(Context context, String library) {
|
| - try {
|
| - String libName = System.mapLibraryName(library);
|
| - File fallbackLibDir = getLibDir(context, LOAD_FROM_APK_FALLBACK_DIR);
|
| - File fallbackLibFile = new File(fallbackLibDir, libName);
|
| - String pathInZipFile = Linker.getLibraryFilePathInZipFile(libName);
|
| - Map<String, File> dstFiles = Collections.singletonMap(pathInZipFile, fallbackLibFile);
|
| -
|
| - deleteObsoleteLibraries(fallbackLibDir, dstFiles.values());
|
| - unpackLibraries(context, dstFiles);
|
| -
|
| - return fallbackLibFile.getAbsolutePath();
|
| - } catch (Exception e) {
|
| - String errorMessage = "Unable to load fallback for library " + library
|
| - + " (" + (e.getMessage() == null ? e.toString() : e.getMessage()) + ")";
|
| - Log.e(TAG, errorMessage, e);
|
| - throw new UnsatisfiedLinkError(errorMessage);
|
| - }
|
| - }
|
| -
|
| - // Delete obsolete libraries from a library folder.
|
| - private static void deleteObsoleteLibraries(File libDir, Collection<File> keptFiles) {
|
| - try {
|
| - // Build a list of libraries that should NOT be deleted.
|
| - Set<String> keptFileNames = new HashSet<String>();
|
| - for (File k : keptFiles) {
|
| - keptFileNames.add(k.getName());
|
| - }
|
| -
|
| - // Delete the obsolete libraries.
|
| - Log.i(TAG, "Deleting obsolete libraries in " + libDir.getPath());
|
| - File[] files = libDir.listFiles();
|
| - if (files != null) {
|
| - for (File f : files) {
|
| - if (!keptFileNames.contains(f.getName())) {
|
| - delete(f);
|
| - }
|
| - }
|
| - } else {
|
| - Log.e(TAG, "Failed to list files in " + libDir.getPath());
|
| - }
|
| -
|
| - // Delete the folder if no libraries were kept.
|
| - if (keptFileNames.isEmpty()) {
|
| - delete(libDir);
|
| - }
|
| - } catch (Exception e) {
|
| - Log.e(TAG, "Failed to remove obsolete libraries from " + libDir.getPath());
|
| - }
|
| - }
|
| -
|
| - // Unpack libraries from a zip file to the file system.
|
| - private static void unpackLibraries(Context context,
|
| - Map<String, File> dstFiles) throws UnpackingException {
|
| - String zipFilePath = context.getApplicationInfo().sourceDir;
|
| - Log.i(TAG, "Opening zip file " + zipFilePath);
|
| - File zipFile = new File(zipFilePath);
|
| - ZipFile zipArchive = openZipFile(zipFile);
|
| -
|
| - try {
|
| - for (Entry<String, File> d : dstFiles.entrySet()) {
|
| - String pathInZipFile = d.getKey();
|
| - File dstFile = d.getValue();
|
| - Log.i(TAG, "Unpacking " + pathInZipFile
|
| - + " to " + dstFile.getAbsolutePath());
|
| - ZipEntry packedLib = zipArchive.getEntry(pathInZipFile);
|
| -
|
| - if (needToUnpackLibrary(zipFile, packedLib, dstFile)) {
|
| - unpackLibraryFromZipFile(zipArchive, packedLib, dstFile);
|
| - setLibraryFilePermissions(dstFile);
|
| - }
|
| - }
|
| - } finally {
|
| - closeZipFile(zipArchive);
|
| - }
|
| - }
|
| -
|
| - // Open a zip file.
|
| - private static ZipFile openZipFile(File zipFile) throws UnpackingException {
|
| - try {
|
| - return new ZipFile(zipFile);
|
| - } catch (ZipException e) {
|
| - throw new UnpackingException("Failed to open zip file " + zipFile.getPath());
|
| - } catch (IOException e) {
|
| - throw new UnpackingException("Failed to open zip file " + zipFile.getPath());
|
| - }
|
| - }
|
| -
|
| - // Determine whether it is necessary to unpack a library from a zip file.
|
| - private static boolean needToUnpackLibrary(
|
| - File zipFile, ZipEntry packedLib, File dstFile) {
|
| - // Check if the fallback library already exists.
|
| - if (!dstFile.exists()) {
|
| - Log.i(TAG, "File " + dstFile.getPath() + " does not exist yet");
|
| - return true;
|
| - }
|
| -
|
| - // Check last modification dates.
|
| - long zipTime = zipFile.lastModified();
|
| - long fallbackLibTime = dstFile.lastModified();
|
| - if (zipTime > fallbackLibTime) {
|
| - Log.i(TAG, "Not using existing fallback file because "
|
| - + "the APK file " + zipFile.getPath()
|
| - + " (timestamp=" + zipTime + ") is newer than "
|
| - + "the fallback library " + dstFile.getPath()
|
| - + "(timestamp=" + fallbackLibTime + ")");
|
| - return true;
|
| - }
|
| -
|
| - // Check file sizes.
|
| - long packedLibSize = packedLib.getSize();
|
| - long fallbackLibSize = dstFile.length();
|
| - if (fallbackLibSize != packedLibSize) {
|
| - Log.i(TAG, "Not using existing fallback file because "
|
| - + "the library in the APK " + zipFile.getPath()
|
| - + " (" + packedLibSize + "B) has a different size than "
|
| - + "the fallback library " + dstFile.getPath()
|
| - + "(" + fallbackLibSize + "B)");
|
| - return true;
|
| - }
|
| -
|
| - Log.i(TAG, "Reusing existing file " + dstFile.getPath());
|
| - return false;
|
| - }
|
| -
|
| - // Unpack a library from a zip file to the filesystem.
|
| - private static void unpackLibraryFromZipFile(ZipFile zipArchive, ZipEntry packedLib,
|
| - File dstFile) throws UnpackingException {
|
| - // Open input stream for the library file inside the zip file.
|
| - InputStream in;
|
| - try {
|
| - in = zipArchive.getInputStream(packedLib);
|
| - } catch (IOException e) {
|
| - throw new UnpackingException(
|
| - "IO exception when locating library in the zip file", e);
|
| - }
|
| -
|
| - // Ensure that the input stream is closed at the end.
|
| - try {
|
| - // Delete existing file if it exists.
|
| - if (dstFile.exists()) {
|
| - Log.i(TAG, "Deleting existing unpacked library file " + dstFile.getPath());
|
| - if (!dstFile.delete()) {
|
| - throw new UnpackingException(
|
| - "Failed to delete existing unpacked library file " + dstFile.getPath());
|
| - }
|
| - }
|
| -
|
| - // Ensure that the library folder exists. Since this is added
|
| - // for increased robustness, we log errors and carry on.
|
| - try {
|
| - dstFile.getParentFile().mkdirs();
|
| - } catch (Exception e) {
|
| - Log.e(TAG, "Failed to make library folder", e);
|
| - }
|
| -
|
| - // Create the destination file.
|
| - try {
|
| - if (!dstFile.createNewFile()) {
|
| - throw new UnpackingException("existing unpacked library file was not deleted");
|
| - }
|
| - } catch (IOException e) {
|
| - throw new UnpackingException("failed to create unpacked library file", e);
|
| - }
|
| -
|
| - // Open the output stream for the destination file.
|
| - OutputStream out;
|
| - try {
|
| - out = new BufferedOutputStream(new FileOutputStream(dstFile));
|
| - } catch (FileNotFoundException e) {
|
| - throw new UnpackingException(
|
| - "failed to open output stream for unpacked library file", e);
|
| - }
|
| -
|
| - // Ensure that the output stream is closed at the end.
|
| - try {
|
| - // Copy the library from the zip file to the destination file.
|
| - Log.i(TAG, "Copying " + packedLib.getName() + " from " + zipArchive.getName()
|
| - + " to " + dstFile.getPath());
|
| - byte[] buffer = new byte[BUFFER_SIZE];
|
| - int len;
|
| - while ((len = in.read(buffer)) != -1) {
|
| - out.write(buffer, 0, len);
|
| - }
|
| - } catch (IOException e) {
|
| - throw new UnpackingException(
|
| - "failed to copy the library from the zip file", e);
|
| - } finally {
|
| - close(out, "output stream");
|
| - }
|
| - } finally {
|
| - close(in, "input stream");
|
| - }
|
| - }
|
| -
|
| - // Set up library file permissions.
|
| - private static void setLibraryFilePermissions(File libFile) {
|
| - // Change permission to rwxr-xr-x
|
| - Log.i(TAG, "Setting file permissions for " + libFile.getPath());
|
| - if (!libFile.setReadable(/* readable */ true, /* ownerOnly */ false)) {
|
| - Log.e(TAG, "failed to chmod a+r the temporary file");
|
| - }
|
| - if (!libFile.setExecutable(/* executable */ true, /* ownerOnly */ false)) {
|
| - Log.e(TAG, "failed to chmod a+x the temporary file");
|
| - }
|
| - if (!libFile.setWritable(/* writable */ true)) {
|
| - Log.e(TAG, "failed to chmod +w the temporary file");
|
| - }
|
| - }
|
| -
|
| - // Close a closable and log a warning if it fails.
|
| - private static void close(Closeable closeable, String name) {
|
| - try {
|
| - closeable.close();
|
| - } catch (IOException e) {
|
| - // Warn and ignore.
|
| - Log.w(TAG, "IO exception when closing " + name, e);
|
| - }
|
| - }
|
| -
|
| - // Close a zip file and log a warning if it fails.
|
| - // This needs to be a separate method because ZipFile is not Closeable in
|
| - // Java 6 (used on some older devices).
|
| - private static void closeZipFile(ZipFile file) {
|
| - try {
|
| - file.close();
|
| - } catch (IOException e) {
|
| - // Warn and ignore.
|
| - Log.w(TAG, "IO exception when closing zip file", e);
|
| - }
|
| - }
|
| -
|
| - // Delete a file and log it.
|
| - private static void delete(File file) {
|
| - if (file.delete()) {
|
| - Log.i(TAG, "Deleted " + file.getPath());
|
| - } else {
|
| - Log.w(TAG, "Failed to delete " + file.getPath());
|
| - }
|
| - }
|
| -}
|
|
|