/*
 * Copyright (C) 2008 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.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.Set;
import java.util.TreeSet;

/**
 * Writes /frameworks/base/preloaded-classes. Also updates
 * {@link LoadedClass#preloaded} fields and writes over compiled log file.
 */
public class WritePreloadedClassFile {

    /**
     * Preload any class that take longer to load than MIN_LOAD_TIME_MICROS us.
     */
    static final int MIN_LOAD_TIME_MICROS = 1250;

    /**
     * Preload any class that was loaded by at least MIN_PROCESSES processes.
     */
    static final int MIN_PROCESSES = 10;

    public static void main(String[] args) throws IOException,
            ClassNotFoundException {
        if (args.length != 1) {
            System.err.println("Usage: WritePreloadedClassFile [compiled log]");
            System.exit(-1);
        }
        String rootFile = args[0];
        Root root = Root.fromFile(rootFile);

        // No classes are preloaded to start.
        for (LoadedClass loadedClass : root.loadedClasses.values()) {
            loadedClass.preloaded = false;
        }

        // Open preloaded-classes file for output.
        Writer out = new BufferedWriter(new OutputStreamWriter(
                new FileOutputStream(Policy.PRELOADED_CLASS_FILE),
                Charset.forName("US-ASCII")));

        out.write("# Classes which are preloaded by"
                + " com.android.internal.os.ZygoteInit.\n");
        out.write("# Automatically generated by frameworks/base/tools/preload/"
            + WritePreloadedClassFile.class.getSimpleName() + ".java.\n");
        out.write("# MIN_LOAD_TIME_MICROS=" + MIN_LOAD_TIME_MICROS + "\n");
        out.write("# MIN_PROCESSES=" + MIN_PROCESSES + "\n");

        /*
         * The set of classes to preload. We preload a class if:
         *
         *  a) it's loaded in the bootclasspath (i.e., is a system class)
         *  b) it takes > MIN_LOAD_TIME_MICROS us to load, and
         *  c) it's loaded by more than one process, or it's loaded by an
         *     application (i.e., not a long running service)
         */
        Set<LoadedClass> toPreload = new TreeSet<LoadedClass>();

        // Preload classes that were loaded by at least 2 processes. Hopefully,
        // the memory associated with these classes will be shared.
        for (LoadedClass loadedClass : root.loadedClasses.values()) {
            Set<String> names = loadedClass.processNames();
            if (!Policy.isPreloadable(loadedClass)) {
                continue;
            }

            if (names.size() >= MIN_PROCESSES ||
                    (loadedClass.medianTimeMicros() > MIN_LOAD_TIME_MICROS && names.size() > 1)) {
                toPreload.add(loadedClass);
            }
        }

        int initialSize = toPreload.size();
        System.out.println(initialSize
                + " classses were loaded by more than one app.");

        // Preload eligable classes from applications (not long-running
        // services).
        for (Proc proc : root.processes.values()) {
            if (proc.fromZygote() && !Policy.isService(proc.name)) {
                for (Operation operation : proc.operations) {
                    LoadedClass loadedClass = operation.loadedClass;
                    if (shouldPreload(loadedClass)) {
                        toPreload.add(loadedClass);
                    }
                }
            }
        }

        System.out.println("Added " + (toPreload.size() - initialSize)
                + " more to speed up applications.");

        System.out.println(toPreload.size()
                + " total classes will be preloaded.");

        // Make classes that were implicitly loaded by the zygote explicit.
        // This adds minimal overhead but avoid confusion about classes not
        // appearing in the list.
        addAllClassesFrom("zygote", root, toPreload);

        for (LoadedClass loadedClass : toPreload) {
            out.write(loadedClass.name + "\n");
        }

        out.close();

        // Update data to reflect LoadedClass.preloaded changes.
        for (LoadedClass loadedClass : toPreload) {
            loadedClass.preloaded = true;
        }
        root.toFile(rootFile);
    }

    private static void addAllClassesFrom(String processName, Root root,
            Set<LoadedClass> toPreload) {
        for (Proc proc : root.processes.values()) {
            if (proc.name.equals(processName)) {
                for (Operation operation : proc.operations) {
                    boolean preloadable
                            = Policy.isPreloadable(operation.loadedClass);
                    if (preloadable) {
                        toPreload.add(operation.loadedClass);
                    }
                }
            }
        }
    }

    /**
     * Returns true if the class should be preloaded.
     */
    private static boolean shouldPreload(LoadedClass clazz) {
        return Policy.isPreloadable(clazz)
                && clazz.medianTimeMicros() > MIN_LOAD_TIME_MICROS;
    }
}
