/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;

class MyClassLoader extends ClassLoader {
    MyClassLoader() throws Exception {
        super(MyClassLoader.class.getClassLoader());

        // Some magic to get access to the pathList field of BaseDexClassLoader.
        ClassLoader loader = getClass().getClassLoader();
        Class<?> baseDexClassLoader = loader.getClass().getSuperclass();
        Field f = baseDexClassLoader.getDeclaredField("pathList");
        f.setAccessible(true);
        Object pathList = f.get(loader);

        // Some magic to get access to the dexField field of pathList.
        f = pathList.getClass().getDeclaredField("dexElements");
        f.setAccessible(true);
        dexElements = (Object[]) f.get(pathList);
        dexFileField = dexElements[0].getClass().getDeclaredField("dexFile");
        dexFileField.setAccessible(true);
    }

    Object[] dexElements;
    Field dexFileField;

    static ClassLoader level1ClassLoader;

    protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {
        if (this != level1ClassLoader) {
            if (className.equals("Level1")) {
                return level1ClassLoader.loadClass(className);
            } else if (className.equals("Level2")) {
                throw new ClassNotFoundException("None of my methods require Level2!");
            } else if (!className.equals("LoadedByMyClassLoader")) {
                // We're only going to handle LoadedByMyClassLoader.
                return getParent().loadClass(className);
            }
        } else {
            if (className != "Level1" && className != "Level2") {
                return getParent().loadClass(className);
            }
        }

        // Mimic what DexPathList.findClass is doing.
        try {
            for (Object element : dexElements) {
                Object dex = dexFileField.get(element);
                Method method = dex.getClass().getDeclaredMethod(
                        "loadClassBinaryName", String.class, ClassLoader.class, List.class);

                if (dex != null) {
                    Class<?> clazz = (Class<?>) method.invoke(dex, className, this, null);
                    if (clazz != null) {
                        return clazz;
                    }
                }
            }
        } catch (Exception e) { /* Ignore */ }
        return null;
    }
}

class LoadedByMyClassLoader {
    public static void bar() {
        Level1.$inline$bar();
    }
}

class Main {
    public static void main(String[] args) throws Exception {
        System.loadLibrary(args[0]);
        // Clone resolved methods, to restore the original version just
        // before we walk the stack in $noinline$bar.
        savedResolvedMethods = cloneResolvedMethods(Main.class);

        MyClassLoader o = new MyClassLoader();
        MyClassLoader.level1ClassLoader = new MyClassLoader();
        Class<?> foo = o.loadClass("LoadedByMyClassLoader");
        Method m = foo.getDeclaredMethod("bar");
        try {
            m.invoke(null);
        } catch (Error e) { /* Ignore */ }
    }

    public static void $inline$bar() {
    }

    public static void $noinline$bar() {
        try {
            // Be evil and clear all dex cache entries.
            Field f = Class.class.getDeclaredField("dexCache");
            f.setAccessible(true);
            Object dexCache = f.get(Main.class);
            f = dexCache.getClass().getDeclaredField("resolvedTypes");
            f.setAccessible(true);
            Object[] array = (Object[]) f.get(dexCache);
            for (int i = 0; i < array.length; i++) {
                array[i] = null;
            }
            restoreResolvedMethods(Main.class, savedResolvedMethods);
        } catch (Throwable t) { /* Ignore */ }

        // This will walk the stack, trying to resolve methods in it.
        // Because we cleared dex cache entries, we will have to find
        // classes again, which require to use the correct class loader
        // in the presence of inlining.
        new Exception().printStackTrace(System.out);
    }
    static Object savedResolvedMethods;

    static native Object cloneResolvedMethods(Class<?> cls);
    static native void restoreResolvedMethods(Class<?> cls, Object saved);
}
