// Copyright 2015 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.incrementalinstall;

import android.content.Context;
import android.os.Build;
import android.util.Log;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

/**
 * Provides the ability to add native libraries and .dex files to an existing class loader.
 * Tested with Jellybean MR2 - Marshmellow.
 */
final class ClassLoaderPatcher {
    private static final String TAG = "cr.incrementalinstall";
    private final File mAppFilesSubDir;
    private final ClassLoader mClassLoader;
    private final Object mLibcoreOs;
    private final int mProcessUid;
    final boolean mIsPrimaryProcess;

    ClassLoaderPatcher(Context context) throws ReflectiveOperationException {
        mAppFilesSubDir =
                new File(context.getApplicationInfo().dataDir, "incremental-install-files");
        mClassLoader = context.getClassLoader();
        mLibcoreOs = Reflect.getField(Class.forName("libcore.io.Libcore"), "os");
        mProcessUid = (Integer) Reflect.invokeMethod(mLibcoreOs, "getuid");
        mIsPrimaryProcess = context.getApplicationInfo().uid == mProcessUid;
        Log.i(TAG, "uid=" + mProcessUid + " (isPrimary=" + mIsPrimaryProcess + ")");
    }

    /**
     * Loads all dex files within |dexDir| into the app's ClassLoader.
     */
    void loadDexFiles(File dexDir) throws ReflectiveOperationException, FileNotFoundException {
        Log.i(TAG, "Installing dex files from: " + dexDir);
        File[] dexFilesArr = dexDir.listFiles();
        if (dexFilesArr == null) {
            throw new FileNotFoundException("Dex dir does not exist: " + dexDir);
        }
        // The optimized dex files will be owned by this process' user.
        // Store them within the app's data dir rather than on /data/local/tmp
        // so that they are still deleted (by the OS) when we uninstall
        // (even on a non-rooted device).
        File incrementalDexesDir = new File(mAppFilesSubDir, "optimized-dexes");
        File isolatedDexesDir = new File(mAppFilesSubDir, "isolated-dexes");
        File optimizedDir;

        if (mIsPrimaryProcess) {
            ensureAppFilesSubDirExists();
            // Allows isolated processes to access the same files.
            incrementalDexesDir.mkdir();
            incrementalDexesDir.setReadable(true, false);
            incrementalDexesDir.setExecutable(true, false);
            // Create a directory for isolated processes to create directories in.
            isolatedDexesDir.mkdir();
            isolatedDexesDir.setWritable(true, false);
            isolatedDexesDir.setExecutable(true, false);

            optimizedDir = incrementalDexesDir;
        } else {
            // There is a UID check of the directory in dalvik.system.DexFile():
            // https://android.googlesource.com/platform/libcore/+/45e0260/dalvik/src/main/java/dalvik/system/DexFile.java#101
            // Rather than have each isolated process run DexOpt though, we use
            // symlinks within the directory to point at the browser process'
            // optimized dex files.
            optimizedDir = new File(isolatedDexesDir, "isolated-" + mProcessUid);
            optimizedDir.mkdir();
            // Always wipe it out and re-create for simplicity.
            Log.i(TAG, "Creating dex file symlinks for isolated process");
            for (File f : optimizedDir.listFiles()) {
                f.delete();
            }
            for (File f : incrementalDexesDir.listFiles()) {
                String to = "../../" + incrementalDexesDir.getName() + "/" + f.getName();
                File from = new File(optimizedDir, f.getName());
                createSymlink(to, from);
            }
        }

        Log.i(TAG, "Code cache dir: " + optimizedDir);
        // TODO(agrieve): Might need to record classpath ordering if we ever have duplicate
        //     class names (since then order will matter here).
        Log.i(TAG, "Loading " + dexFilesArr.length + " dex files");

        Object dexPathList = Reflect.getField(mClassLoader, "pathList");
        Object[] dexElements = (Object[]) Reflect.getField(dexPathList, "dexElements");
        Object[] additionalElements = makeDexElements(dexFilesArr, optimizedDir);
        Reflect.setField(
                dexPathList, "dexElements", Reflect.concatArrays(dexElements, additionalElements));
    }

    /**
     * Sets up all libraries within |libDir| to be loadable by System.loadLibrary().
     */
    void importNativeLibs(File libDir) throws ReflectiveOperationException, IOException {
        Log.i(TAG, "Importing native libraries from: " + libDir);
        // The library copying is not necessary on older devices, but we do it anyways to
        // simplify things (it's fast compared to dexing).
        // https://code.google.com/p/android/issues/detail?id=79480
        File localLibsDir = new File(mAppFilesSubDir, "lib");
        File copyLibsLockFile = new File(mAppFilesSubDir, "libcopy.lock");
        if (mIsPrimaryProcess) {
            // Primary process: Copies native libraries into the app's data directory.
            ensureAppFilesSubDirExists();
            LockFile lockFile = LockFile.acquireRuntimeLock(copyLibsLockFile);
            if (lockFile == null) {
                LockFile.waitForRuntimeLock(copyLibsLockFile, 10 * 1000);
            } else {
                try {
                    localLibsDir.mkdir();
                    localLibsDir.setReadable(true, false);
                    localLibsDir.setExecutable(true, false);
                    copyChangedFiles(libDir, localLibsDir);
                } finally {
                    lockFile.release();
                }
            }
        } else {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                // TODO: Work around this issue by using APK splits to install each dex / lib.
                throw new RuntimeException("Incremental install does not work on Android M+ "
                        + "with isolated processes. Use the gn arg:\n"
                        + "    disable_incremental_isolated_processes=true\n"
                        + "and try again.");
            }
            // Other processes: Waits for primary process to finish copying.
            LockFile.waitForRuntimeLock(copyLibsLockFile, 10 * 1000);
        }
        addNativeLibrarySearchPath(localLibsDir);
    }

    @SuppressWarnings("unchecked")
    private void addNativeLibrarySearchPath(File nativeLibDir) throws ReflectiveOperationException {
        Object dexPathList = Reflect.getField(mClassLoader, "pathList");
        Object currentDirs = Reflect.getField(dexPathList, "nativeLibraryDirectories");
        File[] newDirs = new File[] { nativeLibDir };
        // Switched from an array to an ArrayList in Lollipop.
        if (currentDirs instanceof List) {
            List<File> dirsAsList = (List<File>) currentDirs;
            dirsAsList.add(nativeLibDir);
        } else {
            File[] dirsAsArray = (File[]) currentDirs;
            Reflect.setField(dexPathList, "nativeLibraryDirectories",
                    Reflect.concatArrays(dirsAsArray, newDirs));
        }

        Object[] nativeLibraryPathElements;
        try {
            nativeLibraryPathElements =
                    (Object[]) Reflect.getField(dexPathList, "nativeLibraryPathElements");
        } catch (NoSuchFieldException e) {
            // This field doesn't exist pre-M.
            return;
        }
        Object[] additionalElements = makeNativePathElements(newDirs);
        Reflect.setField(
                dexPathList, "nativeLibraryPathElements",
                Reflect.concatArrays(nativeLibraryPathElements, additionalElements));
    }

    private static void copyChangedFiles(File srcDir, File dstDir) throws IOException {
        // No need to delete stale libs since libraries are loaded explicitly.
        for (File f : srcDir.listFiles()) {
            // Note: Tried using hardlinks, but resulted in EACCES exceptions.
            File dest = new File(dstDir, f.getName());
            copyIfModified(f, dest);
        }
    }

    private static void copyIfModified(File src, File dest) throws IOException {
        long lastModified = src.lastModified();
        if (!dest.exists() || dest.lastModified() != lastModified) {
            Log.i(TAG, "Copying " + src + " -> " + dest);
            FileInputStream istream = new FileInputStream(src);
            FileOutputStream ostream = new FileOutputStream(dest);
            ostream.getChannel().transferFrom(istream.getChannel(), 0, istream.getChannel().size());
            istream.close();
            ostream.close();
            dest.setReadable(true, false);
            dest.setExecutable(true,  false);
            dest.setLastModified(lastModified);
        } else {
            Log.i(TAG, "Up-to-date: " + dest);
        }
    }

    private void ensureAppFilesSubDirExists() {
        mAppFilesSubDir.mkdir();
        mAppFilesSubDir.setExecutable(true, false);
    }

    private void createSymlink(String to, File from) throws ReflectiveOperationException {
        Reflect.invokeMethod(mLibcoreOs, "symlink", to, from.getAbsolutePath());
    }

    private static Object[] makeNativePathElements(File[] paths)
            throws ReflectiveOperationException {
        Class<?> entryClazz = Class.forName("dalvik.system.DexPathList$Element");
        Object[] entries = new Object[paths.length];
        for (int i = 0; i < paths.length; ++i) {
            entries[i] = Reflect.newInstance(entryClazz, paths[i], true, null, null);
        }
        return entries;
    }

    private static Object[] makeDexElements(File[] files, File optimizedDirectory)
            throws ReflectiveOperationException {
        Class<?> entryClazz = Class.forName("dalvik.system.DexPathList$Element");
        Class<?> clazz = Class.forName("dalvik.system.DexPathList");
        Object[] entries = new Object[files.length];
        File emptyDir = new File("");
        for (int i = 0; i < files.length; ++i) {
            File file = files[i];
            Object dexFile = Reflect.invokeMethod(clazz, "loadDexFile", file, optimizedDirectory);
            entries[i] = Reflect.newInstance(entryClazz, emptyDir, false, file, dexFile);
        }
        return entries;
    }
}
