OSDN Git Service

Remove system_server classes from the boot image.
authorNarayan Kamath <narayan@google.com>
Thu, 7 Aug 2014 09:57:40 +0000 (10:57 +0100)
committerNarayan Kamath <narayan@google.com>
Fri, 15 Aug 2014 12:37:03 +0000 (13:37 +0100)
We set the system_server classpath in the environment
(like we do with BOOTCLASSPATH). After the zygote forks
the system_server, we dexopt the classpath (if needed)
and then launch the system server with the correct
PathClassLoader. This needed several small / medium
refactorings :

- The logic for connecting to installd is now in a separate
  class and belongs in the system_server.
- SystemService / SystemServiceManager have now moved to
  classes.jar. They are only used from there, and since they
  use Class.forName, we want them to be loaded by the
  system_server classloader, and not the bootclassloader.
- BootReceiver now moves to frameworks.jar, because it is
  used by ActivityThread and friends.

bug: 16555230

Change-Id: Ic84f0b2baf611eeedff6d123cb7191bb0259e600

21 files changed:
CleanSpec.mk
core/java/android/app/ActivityThread.java
core/java/android/app/ContextImpl.java
core/java/android/app/LoadedApk.java
core/java/com/android/internal/os/InstallerConnection.java [new file with mode: 0644]
core/java/com/android/internal/os/RuntimeInit.java
core/java/com/android/internal/os/ZygoteConnection.java
core/java/com/android/internal/os/ZygoteInit.java
core/java/com/android/server/BootReceiver.java [moved from services/core/java/com/android/server/BootReceiver.java with 100% similarity]
core/jni/AndroidRuntime.cpp
services/appwidget/Android.mk
services/core/java/com/android/server/SystemService.java [moved from core/java/com/android/server/SystemService.java with 100% similarity]
services/core/java/com/android/server/SystemServiceManager.java [moved from core/java/com/android/server/SystemServiceManager.java with 100% similarity]
services/core/java/com/android/server/am/ActivityManagerService.java
services/core/java/com/android/server/pm/Installer.java
services/core/java/com/android/server/pm/PackageManagerService.java
services/core/jni/onload.cpp
services/devicepolicy/Android.mk
services/print/Android.mk
services/restrictions/Android.mk
services/usage/Android.mk

index ae2f3ad..c7cf940 100644 (file)
@@ -218,6 +218,9 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/androi
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services.core_intermediates)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services.core_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services_intermediates)
 
 # ******************************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
index 1b82d8e..fed7ae3 100644 (file)
@@ -1807,9 +1807,9 @@ public final class ActivityThread {
         }
     }
 
-    public void installSystemApplicationInfo(ApplicationInfo info) {
+    public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
         synchronized (this) {
-            getSystemContext().installSystemApplicationInfo(info);
+            getSystemContext().installSystemApplicationInfo(info, classLoader);
 
             // give ourselves a default profiler
             mProfiler = new Profiler();
index 4cf8cb4..da343ac 100644 (file)
@@ -2301,8 +2301,8 @@ class ContextImpl extends Context {
         }
     }
 
-    void installSystemApplicationInfo(ApplicationInfo info) {
-        mPackageInfo.installSystemApplicationInfo(info);
+    void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
+        mPackageInfo.installSystemApplicationInfo(info, classLoader);
     }
 
     final void scheduleFinalCleanup(String who, String what) {
index aa1f021..fcfc1c4 100644 (file)
@@ -199,9 +199,10 @@ public final class LoadedApk {
     /**
      * Sets application info about the system package.
      */
-    void installSystemApplicationInfo(ApplicationInfo info) {
+    void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
         assert info.packageName.equals("android");
         mApplicationInfo = info;
+        mClassLoader = classLoader;
     }
 
     public String getPackageName() {
diff --git a/core/java/com/android/internal/os/InstallerConnection.java b/core/java/com/android/internal/os/InstallerConnection.java
new file mode 100644 (file)
index 0000000..e3f229f
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * 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
+ */
+
+package com.android.internal.os;
+
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
+import android.util.Slog;
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Represents a connection to {@code installd}. Allows multiple connect and
+ * disconnect cycles.
+ *
+ * @hide for internal use only
+ */
+public class InstallerConnection {
+    private static final String TAG = "InstallerConnection";
+    private static final boolean LOCAL_DEBUG = false;
+
+    private InputStream mIn;
+    private OutputStream mOut;
+    private LocalSocket mSocket;
+
+    private final byte buf[] = new byte[1024];
+
+    public InstallerConnection() {
+    }
+
+    public synchronized String transact(String cmd) {
+        if (!connect()) {
+            Slog.e(TAG, "connection failed");
+            return "-1";
+        }
+
+        if (!writeCommand(cmd)) {
+            /*
+             * If installd died and restarted in the background (unlikely but
+             * possible) we'll fail on the next write (this one). Try to
+             * reconnect and write the command one more time before giving up.
+             */
+            Slog.e(TAG, "write command failed? reconnect!");
+            if (!connect() || !writeCommand(cmd)) {
+                return "-1";
+            }
+        }
+        if (LOCAL_DEBUG) {
+            Slog.i(TAG, "send: '" + cmd + "'");
+        }
+
+        final int replyLength = readReply();
+        if (replyLength > 0) {
+            String s = new String(buf, 0, replyLength);
+            if (LOCAL_DEBUG) {
+                Slog.i(TAG, "recv: '" + s + "'");
+            }
+            return s;
+        } else {
+            if (LOCAL_DEBUG) {
+                Slog.i(TAG, "fail");
+            }
+            return "-1";
+        }
+    }
+
+    public int execute(String cmd) {
+        String res = transact(cmd);
+        try {
+            return Integer.parseInt(res);
+        } catch (NumberFormatException ex) {
+            return -1;
+        }
+    }
+
+    public int dexopt(String apkPath, int uid, boolean isPublic, String instructionSet) {
+        StringBuilder builder = new StringBuilder("dexopt");
+        builder.append(' ');
+        builder.append(apkPath);
+        builder.append(' ');
+        builder.append(uid);
+        builder.append(isPublic ? " 1" : " 0");
+        builder.append(" *");         // No pkgName arg present
+        builder.append(' ');
+        builder.append(instructionSet);
+        return execute(builder.toString());
+    }
+
+    public int patchoat(String apkPath, int uid, boolean isPublic, String instructionSet) {
+        StringBuilder builder = new StringBuilder("patchoat");
+        builder.append(' ');
+        builder.append(apkPath);
+        builder.append(' ');
+        builder.append(uid);
+        builder.append(isPublic ? " 1" : " 0");
+        builder.append(" *");         // No pkgName arg present
+        builder.append(' ');
+        builder.append(instructionSet);
+        return execute(builder.toString());
+    }
+
+    private boolean connect() {
+        if (mSocket != null) {
+            return true;
+        }
+        Slog.i(TAG, "connecting...");
+        try {
+            mSocket = new LocalSocket();
+
+            LocalSocketAddress address = new LocalSocketAddress("installd",
+                    LocalSocketAddress.Namespace.RESERVED);
+
+            mSocket.connect(address);
+
+            mIn = mSocket.getInputStream();
+            mOut = mSocket.getOutputStream();
+        } catch (IOException ex) {
+            disconnect();
+            return false;
+        }
+        return true;
+    }
+
+    public void disconnect() {
+        Slog.i(TAG, "disconnecting...");
+        IoUtils.closeQuietly(mSocket);
+        IoUtils.closeQuietly(mIn);
+        IoUtils.closeQuietly(mOut);
+
+        mSocket = null;
+        mIn = null;
+        mOut = null;
+    }
+
+
+    private boolean readFully(byte[] buffer, int len) {
+        try {
+            Streams.readFully(mIn, buffer, 0, len);
+        } catch (IOException ioe) {
+            Slog.e(TAG, "read exception");
+            disconnect();
+            return false;
+        }
+
+        if (LOCAL_DEBUG) {
+            Slog.i(TAG, "read " + len + " bytes");
+        }
+
+        return true;
+    }
+
+    private int readReply() {
+        if (!readFully(buf, 2)) {
+            return -1;
+        }
+
+        final int len = (((int) buf[0]) & 0xff) | ((((int) buf[1]) & 0xff) << 8);
+        if ((len < 1) || (len > buf.length)) {
+            Slog.e(TAG, "invalid reply length (" + len + ")");
+            disconnect();
+            return -1;
+        }
+
+        if (!readFully(buf, len)) {
+            return -1;
+        }
+
+        return len;
+    }
+
+    private boolean writeCommand(String cmdString) {
+        final byte[] cmd = cmdString.getBytes();
+        final int len = cmd.length;
+        if ((len < 1) || (len > buf.length)) {
+            return false;
+        }
+
+        buf[0] = (byte) (len & 0xff);
+        buf[1] = (byte) ((len >> 8) & 0xff);
+        try {
+            mOut.write(buf, 0, 2);
+            mOut.write(cmd, 0, len);
+        } catch (IOException ex) {
+            Slog.e(TAG, "write error");
+            disconnect();
+            return false;
+        }
+        return true;
+    }
+}
index 4a26b4b..d35fce4 100644 (file)
@@ -192,13 +192,14 @@ public class RuntimeInit {
      *
      * @param className Fully-qualified class name
      * @param argv Argument vector for main()
+     * @param classLoader the classLoader to load {@className} with
      */
-    private static void invokeStaticMain(String className, String[] argv)
+    private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
             throws ZygoteInit.MethodAndArgsCaller {
         Class<?> cl;
 
         try {
-            cl = Class.forName(className);
+            cl = Class.forName(className, true, classLoader);
         } catch (ClassNotFoundException ex) {
             throw new RuntimeException(
                     "Missing class when invoking static main " + className,
@@ -263,7 +264,7 @@ public class RuntimeInit {
      * @param targetSdkVersion target SDK version
      * @param argv arg strings
      */
-    public static final void zygoteInit(int targetSdkVersion, String[] argv)
+    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
             throws ZygoteInit.MethodAndArgsCaller {
         if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
 
@@ -272,7 +273,7 @@ public class RuntimeInit {
         commonInit();
         nativeZygoteInit();
 
-        applicationInit(targetSdkVersion, argv);
+        applicationInit(targetSdkVersion, argv, classLoader);
     }
 
     /**
@@ -290,10 +291,10 @@ public class RuntimeInit {
             throws ZygoteInit.MethodAndArgsCaller {
         if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from wrapper");
 
-        applicationInit(targetSdkVersion, argv);
+        applicationInit(targetSdkVersion, argv, null);
     }
 
-    private static void applicationInit(int targetSdkVersion, String[] argv)
+    private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
             throws ZygoteInit.MethodAndArgsCaller {
         // If the application calls System.exit(), terminate the process
         // immediately without running any shutdown hooks.  It is not possible to
@@ -317,7 +318,7 @@ public class RuntimeInit {
         }
 
         // Remaining arguments are passed to the start class's static main
-        invokeStaticMain(args.startClass, args.startArgs);
+        invokeStaticMain(args.startClass, args.startArgs, classLoader);
     }
 
     /**
index 0c48368..43ebb3d 100644 (file)
@@ -863,7 +863,7 @@ class ZygoteConnection {
                         pipeFd, parsedArgs.remainingArgs);
             } else {
                 RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
-                        parsedArgs.remainingArgs);
+                        parsedArgs.remainingArgs, null /* classLoader */);
             }
         } else {
             String className;
index eea4201..051de6e 100644 (file)
@@ -34,8 +34,11 @@ import android.system.Os;
 import android.system.OsConstants;
 import android.util.EventLog;
 import android.util.Log;
+import android.util.Slog;
 import android.webkit.WebViewFactory;
 
+import dalvik.system.DexFile;
+import dalvik.system.PathClassLoader;
 import dalvik.system.VMRuntime;
 
 import libcore.io.IoUtils;
@@ -493,21 +496,69 @@ public class ZygoteInit {
             Process.setArgV0(parsedArgs.niceName);
         }
 
+        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
+        if (systemServerClasspath != null) {
+            performSystemServerDexOpt(systemServerClasspath);
+        }
+
         if (parsedArgs.invokeWith != null) {
+            String[] args = parsedArgs.remainingArgs;
+            // If we have a non-null system server class path, we'll have to duplicate the
+            // existing arguments and append the classpath to it. ART will handle the classpath
+            // correctly when we exec a new process.
+            if (systemServerClasspath != null) {
+                String[] amendedArgs = new String[args.length + 2];
+                amendedArgs[0] = "-cp";
+                amendedArgs[1] = systemServerClasspath;
+                System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
+            }
+
             WrapperInit.execApplication(parsedArgs.invokeWith,
                     parsedArgs.niceName, parsedArgs.targetSdkVersion,
-                    null, parsedArgs.remainingArgs);
+                    null, args);
         } else {
+            ClassLoader cl = null;
+            if (systemServerClasspath != null) {
+                cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());
+                Thread.currentThread().setContextClassLoader(cl);
+            }
+
             /*
              * Pass the remaining arguments to SystemServer.
              */
-            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
+            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
         }
 
         /* should never reach here */
     }
 
     /**
+     * Performs dex-opt on the elements of {@code classPath}, if needed. We
+     * choose the instruction set of the current runtime.
+     */
+    private static void performSystemServerDexOpt(String classPath) {
+        final String[] classPathElements = classPath.split(":");
+        final InstallerConnection installer = new InstallerConnection();
+        final String instructionSet = VMRuntime.getRuntime().vmInstructionSet();
+
+        try {
+            for (String classPathElement : classPathElements) {
+                final byte dexopt = DexFile.isDexOptNeededInternal(classPathElement, "*", instructionSet,
+                        false /* defer */);
+                if (dexopt == DexFile.DEXOPT_NEEDED) {
+                    installer.dexopt(classPathElement, Process.SYSTEM_UID, false, instructionSet);
+                } else if (dexopt == DexFile.PATCHOAT_NEEDED) {
+                    installer.patchoat(classPathElement, Process.SYSTEM_UID, false, instructionSet);
+                }
+            }
+        } catch (IOException ioe) {
+            throw new RuntimeException("Error starting system_server", ioe);
+        } finally {
+            installer.disconnect();
+        }
+    }
+
+    /**
      * Prepare the arguments and fork for the system server process.
      */
     private static boolean startSystemServer(String abiList, String socketName)
index 90c66d7..4098929 100644 (file)
@@ -161,10 +161,8 @@ extern int register_android_text_AndroidCharacter(JNIEnv *env);
 extern int register_android_text_StaticLayout(JNIEnv *env);
 extern int register_android_text_AndroidBidi(JNIEnv *env);
 extern int register_android_opengl_classes(JNIEnv *env);
-extern int register_android_server_fingerprint_FingerprintService(JNIEnv* env);
-extern int register_android_server_NetworkManagementSocketTagger(JNIEnv* env);
-extern int register_android_server_Watchdog(JNIEnv* env);
 extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env);
+extern int register_android_server_NetworkManagementSocketTagger(JNIEnv* env);
 extern int register_com_android_internal_os_ZygoteInit(JNIEnv* env);
 extern int register_android_backup_BackupDataInput(JNIEnv *env);
 extern int register_android_backup_BackupDataOutput(JNIEnv *env);
@@ -1338,9 +1336,7 @@ static const RegJNIRec gRegJNI[] = {
     REG_JNI(register_android_media_ToneGenerator),
 
     REG_JNI(register_android_opengl_classes),
-       REG_JNI(register_android_server_fingerprint_FingerprintService),
     REG_JNI(register_android_server_NetworkManagementSocketTagger),
-    REG_JNI(register_android_server_Watchdog),
     REG_JNI(register_android_ddm_DdmHandleNativeHeap),
     REG_JNI(register_android_backup_BackupDataInput),
     REG_JNI(register_android_backup_BackupDataOutput),
index ca38f2f..e9bab4a 100644 (file)
@@ -7,4 +7,6 @@ LOCAL_MODULE := services.appwidget
 LOCAL_SRC_FILES += \
       $(call all-java-files-under,java)
 
+LOCAL_JAVA_LIBRARIES := services.core
+
 include $(BUILD_STATIC_JAVA_LIBRARY)
index ad2704a..ecd8f11 100755 (executable)
@@ -2031,7 +2031,7 @@ public final class ActivityManagerService extends ActivityManagerNative
 
             ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
                     "android", STOCK_PM_FLAGS);
-            mSystemThread.installSystemApplicationInfo(info);
+            mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
 
             synchronized (this) {
                 ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
index 3e40d3f..d1e03ec 100644 (file)
 
 package com.android.server.pm;
 
-import android.os.Build;
-import com.android.server.SystemService;
-
 import android.content.Context;
 import android.content.pm.PackageStats;
-import android.net.LocalSocket;
-import android.net.LocalSocketAddress;
+import android.os.Build;
 import android.util.Slog;
 import dalvik.system.VMRuntime;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.List;
+import com.android.internal.os.InstallerConnection;
+import com.android.server.SystemService;
 
 public final class Installer extends SystemService {
     private static final String TAG = "Installer";
 
-    private static final boolean LOCAL_DEBUG = false;
-
-    InputStream mIn;
-    OutputStream mOut;
-    LocalSocket mSocket;
-
-    byte buf[] = new byte[1024];
-    int buflen = 0;
+    private final InstallerConnection mInstaller;
 
     public Installer(Context context) {
         super(context);
+        mInstaller = new InstallerConnection();
     }
 
     @Override
@@ -53,154 +41,6 @@ public final class Installer extends SystemService {
         ping();
     }
 
-    private boolean connect() {
-        if (mSocket != null) {
-            return true;
-        }
-        Slog.i(TAG, "connecting...");
-        try {
-            mSocket = new LocalSocket();
-
-            LocalSocketAddress address = new LocalSocketAddress("installd",
-                    LocalSocketAddress.Namespace.RESERVED);
-
-            mSocket.connect(address);
-
-            mIn = mSocket.getInputStream();
-            mOut = mSocket.getOutputStream();
-        } catch (IOException ex) {
-            disconnect();
-            return false;
-        }
-        return true;
-    }
-
-    private void disconnect() {
-        Slog.i(TAG, "disconnecting...");
-        try {
-            if (mSocket != null)
-                mSocket.close();
-        } catch (IOException ex) {
-        }
-        try {
-            if (mIn != null)
-                mIn.close();
-        } catch (IOException ex) {
-        }
-        try {
-            if (mOut != null)
-                mOut.close();
-        } catch (IOException ex) {
-        }
-        mSocket = null;
-        mIn = null;
-        mOut = null;
-    }
-
-    private boolean readBytes(byte buffer[], int len) {
-        int off = 0, count;
-        if (len < 0)
-            return false;
-        while (off != len) {
-            try {
-                count = mIn.read(buffer, off, len - off);
-                if (count <= 0) {
-                    Slog.e(TAG, "read error " + count);
-                    break;
-                }
-                off += count;
-            } catch (IOException ex) {
-                Slog.e(TAG, "read exception");
-                break;
-            }
-        }
-        if (LOCAL_DEBUG) {
-            Slog.i(TAG, "read " + len + " bytes");
-        }
-        if (off == len)
-            return true;
-        disconnect();
-        return false;
-    }
-
-    private boolean readReply() {
-        int len;
-        buflen = 0;
-        if (!readBytes(buf, 2))
-            return false;
-        len = (((int) buf[0]) & 0xff) | ((((int) buf[1]) & 0xff) << 8);
-        if ((len < 1) || (len > 1024)) {
-            Slog.e(TAG, "invalid reply length (" + len + ")");
-            disconnect();
-            return false;
-        }
-        if (!readBytes(buf, len))
-            return false;
-        buflen = len;
-        return true;
-    }
-
-    private boolean writeCommand(String _cmd) {
-        byte[] cmd = _cmd.getBytes();
-        int len = cmd.length;
-        if ((len < 1) || (len > 1024))
-            return false;
-        buf[0] = (byte) (len & 0xff);
-        buf[1] = (byte) ((len >> 8) & 0xff);
-        try {
-            mOut.write(buf, 0, 2);
-            mOut.write(cmd, 0, len);
-        } catch (IOException ex) {
-            Slog.e(TAG, "write error");
-            disconnect();
-            return false;
-        }
-        return true;
-    }
-
-    private synchronized String transaction(String cmd) {
-        if (!connect()) {
-            Slog.e(TAG, "connection failed");
-            return "-1";
-        }
-
-        if (!writeCommand(cmd)) {
-            /*
-             * If installd died and restarted in the background (unlikely but
-             * possible) we'll fail on the next write (this one). Try to
-             * reconnect and write the command one more time before giving up.
-             */
-            Slog.e(TAG, "write command failed? reconnect!");
-            if (!connect() || !writeCommand(cmd)) {
-                return "-1";
-            }
-        }
-        if (LOCAL_DEBUG) {
-            Slog.i(TAG, "send: '" + cmd + "'");
-        }
-        if (readReply()) {
-            String s = new String(buf, 0, buflen);
-            if (LOCAL_DEBUG) {
-                Slog.i(TAG, "recv: '" + s + "'");
-            }
-            return s;
-        } else {
-            if (LOCAL_DEBUG) {
-                Slog.i(TAG, "fail");
-            }
-            return "-1";
-        }
-    }
-
-    private int execute(String cmd) {
-        String res = transaction(cmd);
-        try {
-            return Integer.parseInt(res);
-        } catch (NumberFormatException ex) {
-            return -1;
-        }
-    }
-
     public int install(String name, int uid, int gid, String seinfo) {
         StringBuilder builder = new StringBuilder("install");
         builder.append(' ');
@@ -211,7 +51,7 @@ public final class Installer extends SystemService {
         builder.append(gid);
         builder.append(' ');
         builder.append(seinfo != null ? seinfo : "!");
-        return execute(builder.toString());
+        return mInstaller.execute(builder.toString());
     }
 
     public int patchoat(String apkPath, int uid, boolean isPublic, String pkgName,
@@ -231,7 +71,7 @@ public final class Installer extends SystemService {
         builder.append(pkgName);
         builder.append(' ');
         builder.append(instructionSet);
-        return execute(builder.toString());
+        return mInstaller.execute(builder.toString());
     }
 
     public int patchoat(String apkPath, int uid, boolean isPublic, String instructionSet) {
@@ -240,16 +80,7 @@ public final class Installer extends SystemService {
             return -1;
         }
 
-        StringBuilder builder = new StringBuilder("patchoat");
-        builder.append(' ');
-        builder.append(apkPath);
-        builder.append(' ');
-        builder.append(uid);
-        builder.append(isPublic ? " 1" : " 0");
-        builder.append(" *");         // No pkgName arg present
-        builder.append(' ');
-        builder.append(instructionSet);
-        return execute(builder.toString());
+        return mInstaller.patchoat(apkPath, uid, isPublic, instructionSet);
     }
 
     public int dexopt(String apkPath, int uid, boolean isPublic, String instructionSet) {
@@ -258,16 +89,7 @@ public final class Installer extends SystemService {
             return -1;
         }
 
-        StringBuilder builder = new StringBuilder("dexopt");
-        builder.append(' ');
-        builder.append(apkPath);
-        builder.append(' ');
-        builder.append(uid);
-        builder.append(isPublic ? " 1" : " 0");
-        builder.append(" *");         // No pkgName arg present
-        builder.append(' ');
-        builder.append(instructionSet);
-        return execute(builder.toString());
+        return mInstaller.dexopt(apkPath, uid, isPublic, instructionSet);
     }
 
     public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName,
@@ -287,7 +109,7 @@ public final class Installer extends SystemService {
         builder.append(pkgName);
         builder.append(' ');
         builder.append(instructionSet);
-        return execute(builder.toString());
+        return mInstaller.execute(builder.toString());
     }
 
     public int idmap(String targetApkPath, String overlayApkPath, int uid) {
@@ -298,7 +120,7 @@ public final class Installer extends SystemService {
         builder.append(overlayApkPath);
         builder.append(' ');
         builder.append(uid);
-        return execute(builder.toString());
+        return mInstaller.execute(builder.toString());
     }
 
     public int movedex(String srcPath, String dstPath, String instructionSet) {
@@ -314,7 +136,7 @@ public final class Installer extends SystemService {
         builder.append(dstPath);
         builder.append(' ');
         builder.append(instructionSet);
-        return execute(builder.toString());
+        return mInstaller.execute(builder.toString());
     }
 
     public int rmdex(String codePath, String instructionSet) {
@@ -328,7 +150,7 @@ public final class Installer extends SystemService {
         builder.append(codePath);
         builder.append(' ');
         builder.append(instructionSet);
-        return execute(builder.toString());
+        return mInstaller.execute(builder.toString());
     }
 
     public int remove(String name, int userId) {
@@ -337,7 +159,7 @@ public final class Installer extends SystemService {
         builder.append(name);
         builder.append(' ');
         builder.append(userId);
-        return execute(builder.toString());
+        return mInstaller.execute(builder.toString());
     }
 
     public int rename(String oldname, String newname) {
@@ -346,7 +168,7 @@ public final class Installer extends SystemService {
         builder.append(oldname);
         builder.append(' ');
         builder.append(newname);
-        return execute(builder.toString());
+        return mInstaller.execute(builder.toString());
     }
 
     public int fixUid(String name, int uid, int gid) {
@@ -357,7 +179,7 @@ public final class Installer extends SystemService {
         builder.append(uid);
         builder.append(' ');
         builder.append(gid);
-        return execute(builder.toString());
+        return mInstaller.execute(builder.toString());
     }
 
     public int deleteCacheFiles(String name, int userId) {
@@ -366,7 +188,7 @@ public final class Installer extends SystemService {
         builder.append(name);
         builder.append(' ');
         builder.append(userId);
-        return execute(builder.toString());
+        return mInstaller.execute(builder.toString());
     }
 
     public int deleteCodeCacheFiles(String name, int userId) {
@@ -375,7 +197,7 @@ public final class Installer extends SystemService {
         builder.append(name);
         builder.append(' ');
         builder.append(userId);
-        return execute(builder.toString());
+        return mInstaller.execute(builder.toString());
     }
 
     public int createUserData(String name, int uid, int userId, String seinfo) {
@@ -388,21 +210,21 @@ public final class Installer extends SystemService {
         builder.append(userId);
         builder.append(' ');
         builder.append(seinfo != null ? seinfo : "!");
-        return execute(builder.toString());
+        return mInstaller.execute(builder.toString());
     }
 
     public int createUserConfig(int userId) {
         StringBuilder builder = new StringBuilder("mkuserconfig");
         builder.append(' ');
         builder.append(userId);
-        return execute(builder.toString());
+        return mInstaller.execute(builder.toString());
     }
 
     public int removeUserDataDirs(int userId) {
         StringBuilder builder = new StringBuilder("rmuser");
         builder.append(' ');
         builder.append(userId);
-        return execute(builder.toString());
+        return mInstaller.execute(builder.toString());
     }
 
     public int clearUserData(String name, int userId) {
@@ -411,11 +233,11 @@ public final class Installer extends SystemService {
         builder.append(name);
         builder.append(' ');
         builder.append(userId);
-        return execute(builder.toString());
+        return mInstaller.execute(builder.toString());
     }
 
     public boolean ping() {
-        if (execute("ping") < 0) {
+        if (mInstaller.execute("ping") < 0) {
             return false;
         } else {
             return true;
@@ -423,14 +245,14 @@ public final class Installer extends SystemService {
     }
 
     public int pruneDexCache(String cacheSubDir) {
-        return execute("prunedexcache " + cacheSubDir);
+        return mInstaller.execute("prunedexcache " + cacheSubDir);
     }
 
     public int freeCache(long freeStorageSize) {
         StringBuilder builder = new StringBuilder("freecache");
         builder.append(' ');
         builder.append(String.valueOf(freeStorageSize));
-        return execute(builder.toString());
+        return mInstaller.execute(builder.toString());
     }
 
     public int getSizeInfo(String pkgName, int persona, String apkPath, String libDirPath,
@@ -462,7 +284,7 @@ public final class Installer extends SystemService {
         // just the primary.
         builder.append(instructionSets[0]);
 
-        String s = transaction(builder.toString());
+        String s = mInstaller.transact(builder.toString());
         String res[] = s.split(" ");
 
         if ((res == null) || (res.length != 5)) {
@@ -480,7 +302,7 @@ public final class Installer extends SystemService {
     }
 
     public int moveFiles() {
-        return execute("movefiles");
+        return mInstaller.execute("movefiles");
     }
 
     /**
@@ -506,7 +328,7 @@ public final class Installer extends SystemService {
         builder.append(' ');
         builder.append(userId);
 
-        return execute(builder.toString());
+        return mInstaller.execute(builder.toString());
     }
 
     public boolean restoreconData(String pkgName, String seinfo, int uid) {
@@ -517,7 +339,7 @@ public final class Installer extends SystemService {
         builder.append(seinfo != null ? seinfo : "!");
         builder.append(' ');
         builder.append(uid);
-        return (execute(builder.toString()) == 0);
+        return (mInstaller.execute(builder.toString()) == 0);
     }
 
     /**
index 89bd1d4..304441c 100644 (file)
@@ -1394,16 +1394,27 @@ public class PackageManagerService extends IPackageManager.Stub {
              * list of process files because dexopt will have been run
              * if necessary during zygote startup.
              */
-            String bootClassPath = System.getProperty("java.boot.class.path");
+            final String bootClassPath = System.getenv("BOOTCLASSPATH");
+            final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");
+
             if (bootClassPath != null) {
-                String[] paths = splitString(bootClassPath, ':');
-                for (int i=0; i<paths.length; i++) {
-                    alreadyDexOpted.add(paths[i]);
+                String[] bootClassPathElements = splitString(bootClassPath, ':');
+                for (String element : bootClassPathElements) {
+                    alreadyDexOpted.add(element);
                 }
             } else {
                 Slog.w(TAG, "No BOOTCLASSPATH found!");
             }
 
+            if (systemServerClassPath != null) {
+                String[] systemServerClassPathElements = splitString(systemServerClassPath, ':');
+                for (String element : systemServerClassPathElements) {
+                    alreadyDexOpted.add(element);
+                }
+            } else {
+                Slog.w(TAG, "No SYSTEMSERVERCLASSPATH found!");
+            }
+
             boolean didDexOptLibraryOrTool = false;
 
             final List<String> allInstructionSets = getAllInstructionSets();
index ce2ca9b..39b70a8 100644 (file)
@@ -41,6 +41,8 @@ int register_android_server_hdmi_HdmiCecController(JNIEnv* env);
 int register_android_server_hdmi_HdmiMhlController(JNIEnv* env);
 int register_android_server_tv_TvInputHal(JNIEnv* env);
 int register_android_server_PersistentDataBlockService(JNIEnv* env);
+int register_android_server_fingerprint_FingerprintService(JNIEnv* env);
+int register_android_server_Watchdog(JNIEnv* env);
 };
 
 using namespace android;
@@ -77,6 +79,8 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
     register_android_server_hdmi_HdmiMhlController(env);
     register_android_server_tv_TvInputHal(env);
     register_android_server_PersistentDataBlockService(env);
+    register_android_server_fingerprint_FingerprintService(env);
+    register_android_server_Watchdog(env);
 
     return JNI_VERSION_1_4;
 }
index a55d138..7020f17 100644 (file)
@@ -7,6 +7,6 @@ LOCAL_MODULE := services.devicepolicy
 LOCAL_SRC_FILES += \
       $(call all-java-files-under,java)
 
-LOCAL_JAVA_LIBRARIES := conscrypt
+LOCAL_JAVA_LIBRARIES := conscrypt services.core
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
index 33604b7..00eb2e4 100644 (file)
@@ -7,4 +7,6 @@ LOCAL_MODULE := services.print
 LOCAL_SRC_FILES += \
       $(call all-java-files-under,java)
 
+LOCAL_JAVA_LIBRARIES := services.core
+
 include $(BUILD_STATIC_JAVA_LIBRARY)
index fcf8626..57d1c46 100644 (file)
@@ -7,4 +7,6 @@ LOCAL_MODULE := services.restrictions
 LOCAL_SRC_FILES += \
       $(call all-java-files-under,java)
 
+LOCAL_JAVA_LIBRARIES := services.core
+
 include $(BUILD_STATIC_JAVA_LIBRARY)
index d4b7fa8..f1cbe98 100644 (file)
@@ -7,4 +7,6 @@ LOCAL_MODULE := services.usage
 LOCAL_SRC_FILES += \
       $(call all-java-files-under,java)
 
+LOCAL_JAVA_LIBRARIES := services.core
+
 include $(BUILD_STATIC_JAVA_LIBRARY)