// 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.annotation.SuppressLint;
import android.content.Context;
import android.os.Build;
import android.os.Process;
import android.util.Log;

import dalvik.system.DexFile;

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

/**
 * 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 = "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 = Process.myUid();
        mIsPrimaryProcess = context.getApplicationInfo().uid == mProcessUid;
        Log.i(TAG, "uid=" + mProcessUid + " (isPrimary=" + mIsPrimaryProcess + ")");
    }

    /**
     * Loads all dex files within |dexDir| into the app's ClassLoader.
     */
    @SuppressLint({
            "SetWorldReadable",
            "SetWorldWritable",
    })
    DexFile[] loadDexFiles(File dexDir, String packageName)
            throws ReflectiveOperationException, IOException {
        Log.i(TAG, "Installing dex files from: " + dexDir);

        File optimizedDir = null;
        boolean isAtLeastOreo = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;

        if (isAtLeastOreo) {
            // In O, optimizedDirectory is ignored, and the files are always put in an "oat"
            // directory that is a sibling to the dex files themselves. SELinux policies
            // prevent using odex files from /data/local/tmp, so we must first copy them
            // into the app's data directory in order to get the odex files to live there.
            // Use a package-name subdirectory to prevent name collisions when apk-under-test is
            // used.
            File newDexDir = new File(mAppFilesSubDir, packageName + "-dexes");
            if (mIsPrimaryProcess) {
                safeCopyAllFiles(dexDir, newDexDir);
            }
            dexDir = newDexDir;
        } else {
            // 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");

            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);
        }

        // Ignore "oat" directory.
        // Also ignore files that sometimes show up (e.g. .jar.arm.flock).
        File[] dexFilesArr = dexDir.listFiles(f -> f.getName().endsWith(".jar"));
        if (dexFilesArr == null) {
            throw new FileNotFoundException("Dex dir does not exist: " + dexDir);
        }

        Log.i(TAG, "Loading " + dexFilesArr.length + " dex files");

        Object dexPathList = Reflect.getField(mClassLoader, "pathList");
        Object[] dexElements = (Object[]) Reflect.getField(dexPathList, "dexElements");
        dexElements = addDexElements(dexFilesArr, optimizedDir, dexElements);
        Reflect.setField(dexPathList, "dexElements", dexElements);

        // Return the list of new DexFile instances for the .jars in dexPathList.
        DexFile[] ret = new DexFile[dexFilesArr.length];
        int startIndex = dexElements.length - dexFilesArr.length;
        for (int i = 0; i < ret.length; ++i) {
            ret[i] = (DexFile) Reflect.getField(dexElements[startIndex + i], "dexFile");
        }
        return ret;
    }

    /**
     * Sets up all libraries within |libDir| to be loadable by System.loadLibrary().
     */
    @SuppressLint("SetWorldReadable")
    void importNativeLibs(File libDir) throws ReflectiveOperationException, IOException {
        Log.i(TAG, "Importing native libraries from: " + libDir);
        if (!libDir.exists()) {
            Log.i(TAG, "No native libs exist.");
            return;
        }
        // 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");
        safeCopyAllFiles(libDir, localLibsDir);
        addNativeLibrarySearchPath(localLibsDir);
    }

    @SuppressLint("SetWorldReadable")
    private void safeCopyAllFiles(File srcDir, File dstDir) throws IOException {
        // 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 lockFile = new File(mAppFilesSubDir, dstDir.getName() + ".lock");
        if (mIsPrimaryProcess) {
            ensureAppFilesSubDirExists();
            LockFile lock = LockFile.acquireRuntimeLock(lockFile);
            if (lock == null) {
                LockFile.waitForRuntimeLock(lockFile, 10 * 1000);
            } else {
                try {
                    dstDir.mkdir();
                    dstDir.setReadable(true, false);
                    dstDir.setExecutable(true, false);
                    copyChangedFiles(srcDir, dstDir);
                } finally {
                    lock.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. Build system should have removed this. "
                        + "Please file a bug.");
            }
            // Other processes: Waits for primary process to finish copying.
            LockFile.waitForRuntimeLock(lockFile, 10 * 1000);
        }
    }

    @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(0, nativeLibDir);
        } else {
            File[] dirsAsArray = (File[]) currentDirs;
            Reflect.setField(dexPathList, "nativeLibraryDirectories",
                    Reflect.concatArrays(newDirs, newDirs, dirsAsArray));
        }

        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,
                        nativeLibraryPathElements));
    }

    private static void copyChangedFiles(File srcDir, File dstDir) throws IOException {
        int numUpdated = 0;
        File[] srcFiles = srcDir.listFiles();
        for (File f : srcFiles) {
            // Note: Tried using hardlinks, but resulted in EACCES exceptions.
            File dest = new File(dstDir, f.getName());
            if (copyIfModified(f, dest)) {
                numUpdated++;
            }
        }
        // Delete stale files.
        int numDeleted = 0;
        for (File f : dstDir.listFiles()) {
            File src = new File(srcDir, f.getName());
            if (!src.exists()) {
                numDeleted++;
                f.delete();
            }
        }
        String msg = String.format(Locale.US,
                "copyChangedFiles: %d of %d updated. %d stale files removed.", numUpdated,
                srcFiles.length, numDeleted);
        Log.i(TAG, msg);
    }

    @SuppressLint("SetWorldReadable")
    private static boolean copyIfModified(File src, File dest) throws IOException {
        long lastModified = src.lastModified();
        if (dest.exists() && dest.lastModified() == lastModified) {
            return false;
        }
        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);
        return true;
    }

    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 {
        Object[] entries = new Object[paths.length];
        if (Build.VERSION.SDK_INT >= 26) {
            Class<?> entryClazz = Class.forName("dalvik.system.DexPathList$NativeLibraryElement");
            for (int i = 0; i < paths.length; ++i) {
                entries[i] = Reflect.newInstance(entryClazz, paths[i]);
            }
        } else {
            Class<?> entryClazz = Class.forName("dalvik.system.DexPathList$Element");
            for (int i = 0; i < paths.length; ++i) {
                entries[i] = Reflect.newInstance(entryClazz, paths[i], true, null, null);
            }
        }
        return entries;
    }

    private Object[] addDexElements(File[] files, File optimizedDirectory, Object[] curDexElements)
            throws ReflectiveOperationException {
        Class<?> entryClazz = Class.forName("dalvik.system.DexPathList$Element");
        Class<?> clazz = Class.forName("dalvik.system.DexPathList");
        Object[] ret =
                Reflect.concatArrays(curDexElements, curDexElements, new Object[files.length]);
        File emptyDir = new File("");
        for (int i = 0; i < files.length; ++i) {
            File file = files[i];
            Object dexFile;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                // loadDexFile requires that ret contain all previously added elements.
                dexFile = Reflect.invokeMethod(clazz, "loadDexFile", file, optimizedDirectory,
                                               mClassLoader, ret);
            } else {
                dexFile = Reflect.invokeMethod(clazz, "loadDexFile", file, optimizedDirectory);
            }
            Object dexElement;
            if (Build.VERSION.SDK_INT >= 26) {
                dexElement = Reflect.newInstance(entryClazz, dexFile, file);
            } else {
                dexElement = Reflect.newInstance(entryClazz, emptyDir, false, file, dexFile);
            }
            ret[curDexElements.length + i] = dexElement;
        }
        return ret;
    }
}
