Move preloaded-classes out of framework.jar.

Instead we install preloaded-classes as a standalone configuration file
/system/etc/preloaded-classes, so we can configure different file per product.

Bug: 18305157
Change-Id: I22f1a1dd44f90268d02532bf18405768523c0b1b
diff --git a/Android.mk b/Android.mk
index 22cc27b..7cd6635 100644
--- a/Android.mk
+++ b/Android.mk
@@ -400,9 +400,6 @@
 
 LOCAL_RMTYPEDEFS := true
 
-# List of classes and interfaces which should be loaded by the Zygote.
-LOCAL_JAVA_RESOURCE_FILES += $(LOCAL_PATH)/preloaded-classes
-
 include $(BUILD_JAVA_LIBRARY)
 framework_module := $(LOCAL_INSTALLED_MODULE)
 
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 46850da..62088fa 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -45,6 +45,8 @@
 
 import java.io.BufferedReader;
 import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -91,9 +93,9 @@
     private static Resources mResources;
 
     /**
-     * The name of a resource file that contains classes to preload.
+     * The path of a file that contains classes to preload.
      */
-    private static final String PRELOADED_CLASSES = "preloaded-classes";
+    private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";
 
     /** Controls whether we should preload resources during zygote init. */
     private static final boolean PRELOAD_RESOURCES = true;
@@ -278,74 +280,76 @@
     private static void preloadClasses() {
         final VMRuntime runtime = VMRuntime.getRuntime();
 
-        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream(
-                PRELOADED_CLASSES);
-        if (is == null) {
+        InputStream is;
+        try {
+            is = new FileInputStream(PRELOADED_CLASSES);
+        } catch (FileNotFoundException e) {
             Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
-        } else {
-            Log.i(TAG, "Preloading classes...");
-            long startTime = SystemClock.uptimeMillis();
+            return;
+        }
 
-            // Drop root perms while running static initializers.
-            setEffectiveGroup(UNPRIVILEGED_GID);
-            setEffectiveUser(UNPRIVILEGED_UID);
+        Log.i(TAG, "Preloading classes...");
+        long startTime = SystemClock.uptimeMillis();
 
-            // Alter the target heap utilization.  With explicit GCs this
-            // is not likely to have any effect.
-            float defaultUtilization = runtime.getTargetHeapUtilization();
-            runtime.setTargetHeapUtilization(0.8f);
+        // Drop root perms while running static initializers.
+        setEffectiveGroup(UNPRIVILEGED_GID);
+        setEffectiveUser(UNPRIVILEGED_UID);
 
-            try {
-                BufferedReader br
-                    = new BufferedReader(new InputStreamReader(is), 256);
+        // Alter the target heap utilization.  With explicit GCs this
+        // is not likely to have any effect.
+        float defaultUtilization = runtime.getTargetHeapUtilization();
+        runtime.setTargetHeapUtilization(0.8f);
 
-                int count = 0;
-                String line;
-                while ((line = br.readLine()) != null) {
-                    // Skip comments and blank lines.
-                    line = line.trim();
-                    if (line.startsWith("#") || line.equals("")) {
-                        continue;
-                    }
+        try {
+            BufferedReader br
+                = new BufferedReader(new InputStreamReader(is), 256);
 
-                    try {
-                        if (false) {
-                            Log.v(TAG, "Preloading " + line + "...");
-                        }
-                        Class.forName(line);
-                        count++;
-                    } catch (ClassNotFoundException e) {
-                        Log.w(TAG, "Class not found for preloading: " + line);
-                    } catch (UnsatisfiedLinkError e) {
-                        Log.w(TAG, "Problem preloading " + line + ": " + e);
-                    } catch (Throwable t) {
-                        Log.e(TAG, "Error preloading " + line + ".", t);
-                        if (t instanceof Error) {
-                            throw (Error) t;
-                        }
-                        if (t instanceof RuntimeException) {
-                            throw (RuntimeException) t;
-                        }
-                        throw new RuntimeException(t);
-                    }
+            int count = 0;
+            String line;
+            while ((line = br.readLine()) != null) {
+                // Skip comments and blank lines.
+                line = line.trim();
+                if (line.startsWith("#") || line.equals("")) {
+                    continue;
                 }
 
-                Log.i(TAG, "...preloaded " + count + " classes in "
-                        + (SystemClock.uptimeMillis()-startTime) + "ms.");
-            } catch (IOException e) {
-                Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
-            } finally {
-                IoUtils.closeQuietly(is);
-                // Restore default.
-                runtime.setTargetHeapUtilization(defaultUtilization);
-
-                // Fill in dex caches with classes, fields, and methods brought in by preloading.
-                runtime.preloadDexCaches();
-
-                // Bring back root. We'll need it later.
-                setEffectiveUser(ROOT_UID);
-                setEffectiveGroup(ROOT_GID);
+                try {
+                    if (false) {
+                        Log.v(TAG, "Preloading " + line + "...");
+                    }
+                    Class.forName(line);
+                    count++;
+                } catch (ClassNotFoundException e) {
+                    Log.w(TAG, "Class not found for preloading: " + line);
+                } catch (UnsatisfiedLinkError e) {
+                    Log.w(TAG, "Problem preloading " + line + ": " + e);
+                } catch (Throwable t) {
+                    Log.e(TAG, "Error preloading " + line + ".", t);
+                    if (t instanceof Error) {
+                        throw (Error) t;
+                    }
+                    if (t instanceof RuntimeException) {
+                        throw (RuntimeException) t;
+                    }
+                    throw new RuntimeException(t);
+                }
             }
+
+            Log.i(TAG, "...preloaded " + count + " classes in "
+                    + (SystemClock.uptimeMillis()-startTime) + "ms.");
+        } catch (IOException e) {
+            Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
+        } finally {
+            IoUtils.closeQuietly(is);
+            // Restore default.
+            runtime.setTargetHeapUtilization(defaultUtilization);
+
+            // Fill in dex caches with classes, fields, and methods brought in by preloading.
+            runtime.preloadDexCaches();
+
+            // Bring back root. We'll need it later.
+            setEffectiveUser(ROOT_UID);
+            setEffectiveGroup(ROOT_GID);
         }
     }