Remove system_server classes from the boot image.
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
diff --git a/CleanSpec.mk b/CleanSpec.mk
index ae2f3ad..c7cf940 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -218,6 +218,9 @@
$(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
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 1b82d8e..fed7ae3 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1807,9 +1807,9 @@
}
}
- 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();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 4cf8cb4..da343ac 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2301,8 +2301,8 @@
}
}
- void installSystemApplicationInfo(ApplicationInfo info) {
- mPackageInfo.installSystemApplicationInfo(info);
+ void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
+ mPackageInfo.installSystemApplicationInfo(info, classLoader);
}
final void scheduleFinalCleanup(String who, String what) {
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index aa1f021..fcfc1c49 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -199,9 +199,10 @@
/**
* 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
index 0000000..e3f229f
--- /dev/null
+++ b/core/java/com/android/internal/os/InstallerConnection.java
@@ -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;
+ }
+}
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 4a26b4b..d35fce4 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -192,13 +192,14 @@
*
* @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 @@
* @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 @@
commonInit();
nativeZygoteInit();
- applicationInit(targetSdkVersion, argv);
+ applicationInit(targetSdkVersion, argv, classLoader);
}
/**
@@ -290,10 +291,10 @@
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 @@
}
// Remaining arguments are passed to the start class's static main
- invokeStaticMain(args.startClass, args.startArgs);
+ invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
/**
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 0c48368..43ebb3d 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -863,7 +863,7 @@
pipeFd, parsedArgs.remainingArgs);
} else {
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
- parsedArgs.remainingArgs);
+ parsedArgs.remainingArgs, null /* classLoader */);
}
} else {
String className;
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index eea4201..051de6e 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -34,8 +34,11 @@
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 @@
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)
diff --git a/services/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java
similarity index 100%
rename from services/core/java/com/android/server/BootReceiver.java
rename to core/java/com/android/server/BootReceiver.java
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 90c66d7..4098929 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -161,10 +161,8 @@
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 @@
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),
diff --git a/services/appwidget/Android.mk b/services/appwidget/Android.mk
index ca38f2f..e9bab4a 100644
--- a/services/appwidget/Android.mk
+++ b/services/appwidget/Android.mk
@@ -7,4 +7,6 @@
LOCAL_SRC_FILES += \
$(call all-java-files-under,java)
+LOCAL_JAVA_LIBRARIES := services.core
+
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/core/java/com/android/server/SystemService.java b/services/core/java/com/android/server/SystemService.java
similarity index 100%
rename from core/java/com/android/server/SystemService.java
rename to services/core/java/com/android/server/SystemService.java
diff --git a/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
similarity index 100%
rename from core/java/com/android/server/SystemServiceManager.java
rename to services/core/java/com/android/server/SystemServiceManager.java
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ad2704a..ecd8f11 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2031,7 +2031,7 @@
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);
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 3e40d3f..d1e03ec 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -16,35 +16,23 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
// 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 int moveFiles() {
- return execute("movefiles");
+ return mInstaller.execute("movefiles");
}
/**
@@ -506,7 +328,7 @@
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 @@
builder.append(seinfo != null ? seinfo : "!");
builder.append(' ');
builder.append(uid);
- return (execute(builder.toString()) == 0);
+ return (mInstaller.execute(builder.toString()) == 0);
}
/**
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 89bd1d4..304441c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1394,16 +1394,27 @@
* 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();
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index ce2ca9b..39b70a8 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -41,6 +41,8 @@
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 @@
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;
}
diff --git a/services/devicepolicy/Android.mk b/services/devicepolicy/Android.mk
index a55d138..7020f17 100644
--- a/services/devicepolicy/Android.mk
+++ b/services/devicepolicy/Android.mk
@@ -7,6 +7,6 @@
LOCAL_SRC_FILES += \
$(call all-java-files-under,java)
-LOCAL_JAVA_LIBRARIES := conscrypt
+LOCAL_JAVA_LIBRARIES := conscrypt services.core
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/print/Android.mk b/services/print/Android.mk
index 33604b7..00eb2e4 100644
--- a/services/print/Android.mk
+++ b/services/print/Android.mk
@@ -7,4 +7,6 @@
LOCAL_SRC_FILES += \
$(call all-java-files-under,java)
+LOCAL_JAVA_LIBRARIES := services.core
+
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/restrictions/Android.mk b/services/restrictions/Android.mk
index fcf8626..57d1c46 100644
--- a/services/restrictions/Android.mk
+++ b/services/restrictions/Android.mk
@@ -7,4 +7,6 @@
LOCAL_SRC_FILES += \
$(call all-java-files-under,java)
+LOCAL_JAVA_LIBRARIES := services.core
+
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/usage/Android.mk b/services/usage/Android.mk
index d4b7fa8..f1cbe98 100644
--- a/services/usage/Android.mk
+++ b/services/usage/Android.mk
@@ -7,4 +7,6 @@
LOCAL_SRC_FILES += \
$(call all-java-files-under,java)
+LOCAL_JAVA_LIBRARIES := services.core
+
include $(BUILD_STATIC_JAVA_LIBRARY)