Updated preloaded-classes file.
diff --git a/tools/preload/20090811.compiled b/tools/preload/20090811.compiled
new file mode 100644
index 0000000..dd61487
--- /dev/null
+++ b/tools/preload/20090811.compiled
Binary files differ
diff --git a/tools/preload/ClassRank.java b/tools/preload/ClassRank.java
index 3699b89..c562d5c 100644
--- a/tools/preload/ClassRank.java
+++ b/tools/preload/ClassRank.java
@@ -26,7 +26,7 @@
      * Increase this number to add more weight to classes which were loaded
      * earlier.
      */
-    static final int SEQUENCE_WEIGHT = 500; // 5 ms
+    static final int SEQUENCE_WEIGHT = 500; // 0.5ms
 
     static final int BUCKET_SIZE = 5;
 
diff --git a/tools/preload/LoadedClass.java b/tools/preload/LoadedClass.java
index 5782807..9ef17f5 100644
--- a/tools/preload/LoadedClass.java
+++ b/tools/preload/LoadedClass.java
@@ -15,10 +15,7 @@
  */
 
 import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 /**
  * A loaded class.
@@ -54,7 +51,7 @@
     }
 
     void measureMemoryUsage() {
-        this.memoryUsage = MemoryUsage.forClass(name);        
+//        this.memoryUsage = MemoryUsage.forClass(name);
     }
 
     int mlt = -1;
@@ -102,31 +99,20 @@
         }
     }
 
-    /**
-     * Counts loads by apps.
-     */
-    int appLoads() {
-        return operationsByApps(loads);
+    /** Returns names of apps that loaded this class. */
+    Set<String> applicationNames() {
+        Set<String> appNames = new HashSet<String>();
+        addProcessNames(loads, appNames);
+        addProcessNames(initializations, appNames);
+        return appNames;
     }
 
-    /**
-     * Counts inits by apps.
-     */
-    int appInits() {
-        return operationsByApps(initializations);
-    }
-
-    /**
-     * Counts number of app operations in the given list.
-     */
-    private static int operationsByApps(List<Operation> operations) {
-        int byApps = 0;
-        for (Operation operation : operations) {
+    private void addProcessNames(List<Operation> ops, Set<String> appNames) {
+        for (Operation operation : ops) {
             if (operation.process.isApplication()) {
-                byApps++;
+                appNames.add(operation.process.name);
             }
         }
-        return byApps;
     }
 
     public int compareTo(LoadedClass o) {
@@ -160,4 +146,8 @@
 
         return false;
     }
+
+    public boolean isPreloadable() {
+        return systemClass && Policy.isPreloadableClass(name);
+    }
 }
diff --git a/tools/preload/Policy.java b/tools/preload/Policy.java
index 554966b..ade889e3 100644
--- a/tools/preload/Policy.java
+++ b/tools/preload/Policy.java
@@ -24,47 +24,32 @@
 public class Policy {
     
     /**
+     * No constructor - use static methods only
+     */
+    private Policy() {}
+
+    /**
      * This location (in the build system) of the preloaded-classes file.
      */
-    private static final String PRELOADED_CLASS_FILE = "frameworks/base/preloaded-classes";
-    
+    private static final String PRELOADED_CLASS_FILE
+            = "frameworks/base/preloaded-classes";
+
     /**
-     * The internal process name of the system process.  Note, this also shows up as
-     * "system_process", e.g. in ddms.
-     */
-    private static final String SYSTEM_SERVER_PROCESS_NAME = "system_server";
-
-    /** 
-     * Names of non-application processes - these will not be checked for preloaded classes.
-     * 
-     * TODO: Replace this hardcoded list with a walk up the parent chain looking for zygote.
-     */
-    private static final Set<String> NOT_FROM_ZYGOTE = new HashSet<String>(Arrays.asList(
-            "zygote",
-            "dexopt",
-            "unknown",
-            SYSTEM_SERVER_PROCESS_NAME,
-            "com.android.development",
-            "app_process" // am & other shell commands
-    ));
-
-    /** 
-     * Long running services.  These are restricted in their contribution to the preloader
-     * because their launch time is less critical.
+     * Long running services. These are restricted in their contribution to the 
+     * preloader because their launch time is less critical.
      */
     private static final Set<String> SERVICES = new HashSet<String>(Arrays.asList(
-            SYSTEM_SERVER_PROCESS_NAME,
-            "com.android.acore",
-         // Commented out to make sure DefaultTimeZones gets preloaded.
-         // "com.android.phone",
+            "system_server",
             "com.google.process.content",
-            "android.process.media"
+            "android.process.media",
+            "com.google.process.gapps"
     ));
 
     /**
      * Classes which we shouldn't load from the Zygote.
      */
-    private static final Set<String> EXCLUDED_CLASSES = new HashSet<String>(Arrays.asList(
+    private static final Set<String> EXCLUDED_CLASSES
+            = new HashSet<String>(Arrays.asList(
         // Binders
         "android.app.AlarmManager",
         "android.app.SearchManager",
@@ -75,15 +60,9 @@
         "android.os.AsyncTask",
         "android.pim.ContactsAsyncHelper",
         "java.lang.ProcessManager"
-        
     ));
 
     /**
-     * No constructor - use static methods only
-     */
-    private Policy() {}
-    
-    /**
      * Returns the path/file name of the preloaded classes file that will be written 
      * by WritePreloadedClassFile.
      */
@@ -92,13 +71,6 @@
     }
     
     /**
-     * Reports if a given process name was created from zygote
-     */
-    public static boolean isFromZygote(String processName) {
-        return !NOT_FROM_ZYGOTE.contains(processName);
-    }
-    
-    /**
      * Reports if the given process name is a "long running" process or service
      */
     public static boolean isService(String processName) {
diff --git a/tools/preload/PrintCsv.java b/tools/preload/PrintCsv.java
index 9f2a318..62f4271 100644
--- a/tools/preload/PrintCsv.java
+++ b/tools/preload/PrintCsv.java
@@ -18,6 +18,9 @@
 import java.io.FileInputStream;
 import java.io.ObjectInputStream;
 import java.io.BufferedInputStream;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.TreeSet;
 
 /**
  * Prints raw information in CSV format.
@@ -37,13 +40,14 @@
                 + ",Preloaded"
                 + ",Median Load Time (us)"
                 + ",Median Init Time (us)"
+                + ",Process Names"
                 + ",Load Count"
-                + ",Init Count"
-                + ",Managed Heap (B)"
-                + ",Native Heap (B)"
-                + ",Managed Pages (kB)"
-                + ",Native Pages (kB)"
-                + ",Other Pages (kB)");
+                + ",Init Count");
+//                + ",Managed Heap (B)"
+//                + ",Native Heap (B)"
+//                + ",Managed Pages (kB)"
+//                + ",Native Pages (kB)"
+//                + ",Other Pages (kB)");
 
         MemoryUsage baseline = root.baseline;
 
@@ -60,10 +64,23 @@
             System.out.print(',');
             System.out.print(loadedClass.medianInitTimeMicros());
             System.out.print(',');
+            System.out.print('"');
+
+            Set<String> procNames = new TreeSet<String>();
+            for (Operation op : loadedClass.loads)
+                procNames.add(op.process.name);
+            for (Operation op : loadedClass.initializations)
+                procNames.add(op.process.name);
+            for (String name : procNames) {
+                System.out.print(name + "\n");
+            }
+            
+            System.out.print('"');
+            System.out.print(',');
             System.out.print(loadedClass.loads.size());
             System.out.print(',');
             System.out.print(loadedClass.initializations.size());
-
+/*
             if (loadedClass.memoryUsage.isAvailable()) {
                 MemoryUsage subtracted
                         = loadedClass.memoryUsage.subtract(baseline);
@@ -82,7 +99,7 @@
             } else {
                 System.out.print(",n/a,n/a,n/a,n/a,n/a");
             }
-
+*/
             System.out.println();
         }
     }
diff --git a/tools/preload/Proc.java b/tools/preload/Proc.java
index 22697f8..66e04dc 100644
--- a/tools/preload/Proc.java
+++ b/tools/preload/Proc.java
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-import java.util.Set;
-import java.util.HashSet;
 import java.util.Arrays;
 import java.util.List;
 import java.util.ArrayList;
@@ -23,7 +21,6 @@
 import java.util.Map;
 import java.util.HashMap;
 import java.util.Collections;
-import java.util.TreeSet;
 import java.io.Serializable;
 
 /**
@@ -38,11 +35,6 @@
      */
     static final int PERCENTAGE_TO_PRELOAD = 75;
 
-    /**
-     * Maximum number of classes to preload for a given process.
-     */
-    static final int MAX_TO_PRELOAD = 100;
-
     /** Parent process. */
     final Proc parent;
 
@@ -97,11 +89,9 @@
 
     /**
      * Returns a list of classes which should be preloaded.
-     * 
-     * @param takeAllClasses forces all classes to be taken (irrespective of ranking)
      */
-    List<LoadedClass> highestRankedClasses(boolean takeAllClasses) {
-        if (!isApplication()) {
+    List<LoadedClass> highestRankedClasses() {
+        if (!isApplication() || Policy.isService(this.name)) {
             return Collections.emptyList();
         }
 
@@ -114,25 +104,13 @@
         int timeToSave = totalTimeMicros() * percentageToPreload() / 100;
         int timeSaved = 0;
 
-        boolean service = Policy.isService(this.name);
-
+        int count = 0;
         List<LoadedClass> highest = new ArrayList<LoadedClass>();
         for (Operation operation : ranked) {
-            
-            // These are actual ranking decisions, which can be overridden
-            if (!takeAllClasses) {
-                if (highest.size() >= MAX_TO_PRELOAD) {
-                    System.out.println(name + " got " 
-                            + (timeSaved * 100 / timeToSave) + "% through");
-                    break;
-                }
-    
-                if (timeSaved >= timeToSave) {
-                    break;
-                }
+            if (timeSaved >= timeToSave || count++ > 100) {
+                break;
             }
 
-            // The remaining rules apply even to wired-down processes
             if (!Policy.isPreloadableClass(operation.loadedClass.name)) {
                 continue;
             }
@@ -140,13 +118,8 @@
             if (!operation.loadedClass.systemClass) {
                 continue;
             }
-
-            // Only load java.* class for services.
-            if (!service || operation.loadedClass.name.startsWith("java.")) {
-                highest.add(operation.loadedClass);
-            }
-
-            // For services, still count the time even if it's not in java.* 
+    
+            highest.add(operation.loadedClass);
             timeSaved += operation.medianExclusiveTimeMicros();
         }
 
@@ -166,11 +139,13 @@
 
     /** 
      * Returns true if this process is an app.
-     *      
-     * TODO: Replace the hardcoded list with a walk up the parent chain looking for zygote.
      */
     public boolean isApplication() {
-        return Policy.isFromZygote(name);
+        if (name.equals("com.android.development")) {
+            return false;
+        }
+
+        return parent != null && parent.name.equals("zygote");
     }
 
     /**
diff --git a/tools/preload/WritePreloadedClassFile.java b/tools/preload/WritePreloadedClassFile.java
index d87b1f0..b209af0 100644
--- a/tools/preload/WritePreloadedClassFile.java
+++ b/tools/preload/WritePreloadedClassFile.java
@@ -20,8 +20,6 @@
 import java.io.OutputStreamWriter;
 import java.io.Writer;
 import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
 
@@ -32,71 +30,85 @@
 public class WritePreloadedClassFile {
 
     public static void main(String[] args) throws IOException, ClassNotFoundException {
-        
-        // Process command-line arguments first
-        List<String> wiredProcesses = new ArrayList<String>();
-        String inputFileName = null;
-        int argOffset = 0;
-        try {
-            while ("--preload-all-process".equals(args[argOffset])) {
-                argOffset++;
-                wiredProcesses.add(args[argOffset++]);
-            }
-            
-            inputFileName = args[argOffset++];
-        } catch (RuntimeException e) {
-            System.err.println("Usage: WritePreloadedClassFile " +
-                    "[--preload-all-process process-name] " +
-                    "[compiled log file]");
-            System.exit(0);
+        if (args.length != 1) {
+            System.err.println("Usage: WritePreloadedClassFile [compiled log]");
+            System.exit(-1);
         }
+        String rootFile = args[0];
+        Root root = Root.fromFile(rootFile);
 
-        Root root = Root.fromFile(inputFileName);
-
+        // 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.getPreloadedClassFileName()),
                 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.\n");
-        out.write("# percent=" + Proc.PERCENTAGE_TO_PRELOAD + ", weight="
-                + ClassRank.SEQUENCE_WEIGHT
+        out.write("# percent=" + Proc.PERCENTAGE_TO_PRELOAD
+                + ", weight=" + ClassRank.SEQUENCE_WEIGHT
                 + ", bucket_size=" + ClassRank.BUCKET_SIZE
                 + "\n");
-        for (String wiredProcess : wiredProcesses) {
-            out.write("# forcing classes loaded by: " + wiredProcess + "\n");
-        }
 
-        Set<LoadedClass> highestRanked = new TreeSet<LoadedClass>();
-        for (Proc proc : root.processes.values()) {
-            // test to see if this is one of the wired-down ("take all classes") processes
-            boolean isWired = wiredProcesses.contains(proc.name);
-            
-            List<LoadedClass> highestForProc = proc.highestRankedClasses(isWired);
+        Set<LoadedClass> toPreload = new TreeSet<LoadedClass>();
 
-            System.out.println(proc.name + ": " + highestForProc.size());
-
-            for (LoadedClass loadedClass : highestForProc) {
-                loadedClass.preloaded = true;
+        // Preload all classes that were loaded by at least 2 apps, if both
+        // apps run at the same time, they'll share memory.
+        for (LoadedClass loadedClass : root.loadedClasses.values()) {
+            if (!loadedClass.isPreloadable()) {
+                continue;
             }
-            highestRanked.addAll(highestForProc);
+
+            Set<String> appNames = loadedClass.applicationNames();
+
+            if (appNames.size() > 3) {
+                toPreload.add(loadedClass);
+            }
         }
 
-        for (LoadedClass loadedClass : highestRanked) {
+        // Try to make individual apps start faster by preloading slowest
+        // classes.
+        for (Proc proc : root.processes.values()) {
+            toPreload.addAll(proc.highestRankedClasses());
+        }
+
+        System.out.println(toPreload.size() + " classes will be preloaded.");
+
+        // Make classes that were already loaded by the zygote explicit.
+        // This adds minimal overhead but avoid confusion about classes not
+        // appearing in the list.
+        addAllClassesFor("zygote", root, toPreload);
+
+        for (LoadedClass loadedClass : toPreload) {
             out.write(loadedClass.name);
             out.write('\n');
         }
 
         out.close();
 
-        System.out.println(highestRanked.size()
-                + " classes will be preloaded.");
-
         // Update data to reflect LoadedClass.preloaded changes.
-        root.toFile(inputFileName);
+        for (LoadedClass loadedClass : toPreload) {
+            loadedClass.preloaded = true;
+        }
+        root.toFile(rootFile);
+    }
+
+    private static void addAllClassesFor(String packageName, Root root,
+                                         Set<LoadedClass> toPreload) {
+        for (Proc proc : root.processes.values()) {
+            if (proc.name.equals(packageName)) {
+                for (Operation operation : proc.operations) {
+                    // TODO: I'm not sure how the zygote loaded classes that
+                    // aren't supposed to be preloadable...
+                    if (operation.loadedClass.isPreloadable()) {
+                        toPreload.add(operation.loadedClass);
+                    }
+                }
+            }
+        }
     }
 }
diff --git a/tools/preload/preload.iml b/tools/preload/preload.iml
index d1fab57..2d87c55 100644
--- a/tools/preload/preload.iml
+++ b/tools/preload/preload.iml
@@ -1,15 +1,14 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <module relativePaths="true" type="JAVA_MODULE" version="4">
   <component name="NewModuleRootManager" inherit-compiler-output="false">
-    <output url="file:///tmp/preload/" />
+    <output url="file:///tmp/preload" />
+    <output-test url="file:///tmp/preload" />
     <exclude-output />
-    <output-test url="file:///tmp/preload/" />
     <content url="file://$MODULE_DIR$">
       <sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntryProperties />
   </component>
 </module>
 
diff --git a/tools/preload/preload.ipr b/tools/preload/preload.ipr
index c5613ad..f78bf76 100644
--- a/tools/preload/preload.ipr
+++ b/tools/preload/preload.ipr
@@ -114,6 +114,7 @@
     <option name="ADDITIONAL_OPTIONS_STRING" value="" />
     <option name="MAXIMUM_HEAP_SIZE" value="128" />
   </component>
+  <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
   <component name="EntryPointsManager">
     <entry_points version="2.0" />
   </component>
@@ -125,13 +126,13 @@
   <component name="IdProvider" IDEtalkID="D171F99B9178C1675593DC9A76A5CC7E" />
   <component name="InspectionProjectProfileManager">
     <option name="PROJECT_PROFILE" value="Project Default" />
-    <option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
-    <scopes />
+    <option name="USE_PROJECT_PROFILE" value="true" />
+    <version value="1.0" />
     <profiles>
       <profile version="1.0" is_locked="false">
         <option name="myName" value="Project Default" />
         <option name="myLocal" value="false" />
-        <inspection_tool class="JavaDoc" level="WARNING" enabled="false">
+        <inspection_tool class="JavaDoc" enabled="false" level="WARNING" enabled_by_default="false">
           <option name="TOP_LEVEL_CLASS_OPTIONS">
             <value>
               <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
@@ -160,14 +161,19 @@
           <option name="IGNORE_JAVADOC_PERIOD" value="true" />
           <option name="myAdditionalJavadocTags" value="" />
         </inspection_tool>
-        <inspection_tool class="OnDemandImport" level="WARNING" enabled="true" />
-        <inspection_tool class="SamePackageImport" level="WARNING" enabled="true" />
-        <inspection_tool class="JavaLangImport" level="WARNING" enabled="true" />
-        <inspection_tool class="RedundantImport" level="WARNING" enabled="true" />
-        <inspection_tool class="UnusedImport" level="WARNING" enabled="true" />
+        <inspection_tool class="JavaLangImport" enabled="true" level="WARNING" enabled_by_default="true" />
+        <inspection_tool class="OnDemandImport" enabled="true" level="WARNING" enabled_by_default="true" />
+        <inspection_tool class="RedundantImport" enabled="true" level="WARNING" enabled_by_default="true" />
+        <inspection_tool class="SamePackageImport" enabled="true" level="WARNING" enabled_by_default="true" />
+        <inspection_tool class="UnusedImport" enabled="true" level="WARNING" enabled_by_default="true" />
       </profile>
     </profiles>
-    <list size="0" />
+    <list size="4">
+      <item index="0" class="java.lang.String" itemvalue="WARNING" />
+      <item index="1" class="java.lang.String" itemvalue="SERVER PROBLEM" />
+      <item index="2" class="java.lang.String" itemvalue="INFO" />
+      <item index="3" class="java.lang.String" itemvalue="ERROR" />
+    </list>
   </component>
   <component name="JavacSettings">
     <option name="DEBUGGING_INFO" value="true" />
@@ -332,13 +338,19 @@
     <option name="USE_CLIENT_FILTER" value="true" />
     <option name="CLIENT" value="" />
   </component>
+  <component name="ProjectDetails">
+    <option name="projectName" value="preload" />
+  </component>
   <component name="ProjectFileVersion" converted="true" />
+  <component name="ProjectKey">
+    <option name="state" value="project:///Volumes/Android/donut/frameworks/base/tools/preload/preload.ipr" />
+  </component>
   <component name="ProjectModuleManager">
     <modules>
       <module fileurl="file://$PROJECT_DIR$/preload.iml" filepath="$PROJECT_DIR$/preload.iml" />
     </modules>
   </component>
-  <component name="ProjectRootManager" version="2" assert-keyword="true" jdk-15="true" project-jdk-name="1.5" project-jdk-type="JavaSDK">
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.5" project-jdk-type="JavaSDK">
     <output url="file:///tmp/preload" />
   </component>
   <component name="RmicSettings">
@@ -374,6 +386,9 @@
     <option name="myValidatorValidationEnabled" value="true" />
     <option name="myReportErrorsAsWarnings" value="true" />
   </component>
+  <component name="SvnBranchConfigurationManager">
+    <option name="mySupportsUserInfoFilter" value="true" />
+  </component>
   <component name="SvnChangesBrowserSettings">
     <option name="USE_AUTHOR_FIELD" value="true" />
     <option name="AUTHOR" value="" />
@@ -381,15 +396,6 @@
     <option name="USE_PROJECT_SETTINGS" value="true" />
     <option name="USE_ALTERNATE_LOCATION" value="false" />
   </component>
-  <component name="SvnConfiguration">
-    <option name="USER" value="" />
-    <option name="PASSWORD" value="" />
-    <option name="PROCESS_UNRESOLVED" value="false" />
-    <option name="LAST_MERGED_REVISION" />
-    <option name="UPDATE_RUN_STATUS" value="false" />
-    <option name="UPDATE_RECURSIVELY" value="true" />
-    <option name="MERGE_DRY_RUN" value="false" />
-  </component>
   <component name="VCS.FileViewConfiguration">
     <option name="SELECTED_STATUSES" value="DEFAULT" />
     <option name="SELECTED_COLUMNS" value="DEFAULT" />