diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/app/ActivityThread.java | 4 | ||||
-rw-r--r-- | core/java/android/app/ContextImpl.java | 4 | ||||
-rw-r--r-- | core/java/android/app/LoadedApk.java | 3 | ||||
-rw-r--r-- | core/java/com/android/internal/os/InstallerConnection.java | 207 | ||||
-rw-r--r-- | core/java/com/android/internal/os/RuntimeInit.java | 15 | ||||
-rw-r--r-- | core/java/com/android/internal/os/ZygoteConnection.java | 2 | ||||
-rw-r--r-- | core/java/com/android/internal/os/ZygoteInit.java | 55 | ||||
-rw-r--r-- | core/java/com/android/server/BootReceiver.java | 260 | ||||
-rw-r--r-- | core/java/com/android/server/SystemService.java | 199 | ||||
-rw-r--r-- | core/java/com/android/server/SystemServiceManager.java | 227 | ||||
-rw-r--r-- | core/jni/AndroidRuntime.cpp | 6 |
11 files changed, 536 insertions, 446 deletions
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 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(); 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 @@ 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) { diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index aa1f021..fcfc1c4 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -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 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 @@ 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); } /** 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 @@ class ZygoteConnection { 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.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) diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java new file mode 100644 index 0000000..7249985 --- /dev/null +++ b/core/java/com/android/server/BootReceiver.java @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2009 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.server; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.IPackageManager; +import android.os.Build; +import android.os.DropBoxManager; +import android.os.FileObserver; +import android.os.FileUtils; +import android.os.RecoverySystem; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.SystemProperties; +import android.provider.Downloads; +import android.util.Slog; + +import java.io.File; +import java.io.IOException; + +/** + * Performs a number of miscellaneous, non-system-critical actions + * after the system has finished booting. + */ +public class BootReceiver extends BroadcastReceiver { + private static final String TAG = "BootReceiver"; + + // Maximum size of a logged event (files get truncated if they're longer). + // Give userdebug builds a larger max to capture extra debug, esp. for last_kmsg. + private static final int LOG_SIZE = + SystemProperties.getInt("ro.debuggable", 0) == 1 ? 98304 : 65536; + + private static final File TOMBSTONE_DIR = new File("/data/tombstones"); + + // The pre-froyo package and class of the system updater, which + // ran in the system process. We need to remove its packages here + // in order to clean up after a pre-froyo-to-froyo update. + private static final String OLD_UPDATER_PACKAGE = + "com.google.android.systemupdater"; + private static final String OLD_UPDATER_CLASS = + "com.google.android.systemupdater.SystemUpdateReceiver"; + + // Keep a reference to the observer so the finalizer doesn't disable it. + private static FileObserver sTombstoneObserver = null; + + @Override + public void onReceive(final Context context, Intent intent) { + // Log boot events in the background to avoid blocking the main thread with I/O + new Thread() { + @Override + public void run() { + try { + logBootEvents(context); + } catch (Exception e) { + Slog.e(TAG, "Can't log boot events", e); + } + try { + boolean onlyCore = false; + try { + onlyCore = IPackageManager.Stub.asInterface(ServiceManager.getService( + "package")).isOnlyCoreApps(); + } catch (RemoteException e) { + } + if (!onlyCore) { + removeOldUpdatePackages(context); + } + } catch (Exception e) { + Slog.e(TAG, "Can't remove old update packages", e); + } + + } + }.start(); + } + + private void removeOldUpdatePackages(Context context) { + Downloads.removeAllDownloadsByPackage(context, OLD_UPDATER_PACKAGE, OLD_UPDATER_CLASS); + } + + private void logBootEvents(Context ctx) throws IOException { + final DropBoxManager db = (DropBoxManager) ctx.getSystemService(Context.DROPBOX_SERVICE); + final SharedPreferences prefs = ctx.getSharedPreferences("log_files", Context.MODE_PRIVATE); + final String headers = new StringBuilder(512) + .append("Build: ").append(Build.FINGERPRINT).append("\n") + .append("Hardware: ").append(Build.BOARD).append("\n") + .append("Revision: ") + .append(SystemProperties.get("ro.revision", "")).append("\n") + .append("Bootloader: ").append(Build.BOOTLOADER).append("\n") + .append("Radio: ").append(Build.RADIO).append("\n") + .append("Kernel: ") + .append(FileUtils.readTextFile(new File("/proc/version"), 1024, "...\n")) + .append("\n").toString(); + final String bootReason = SystemProperties.get("ro.boot.bootreason", null); + + String recovery = RecoverySystem.handleAftermath(); + if (recovery != null && db != null) { + db.addText("SYSTEM_RECOVERY_LOG", headers + recovery); + } + + String lastKmsgFooter = ""; + if (bootReason != null) { + lastKmsgFooter = new StringBuilder(512) + .append("\n") + .append("Boot info:\n") + .append("Last boot reason: ").append(bootReason).append("\n") + .toString(); + } + + if (SystemProperties.getLong("ro.runtime.firstboot", 0) == 0) { + String now = Long.toString(System.currentTimeMillis()); + SystemProperties.set("ro.runtime.firstboot", now); + if (db != null) db.addText("SYSTEM_BOOT", headers); + + // Negative sizes mean to take the *tail* of the file (see FileUtils.readTextFile()) + addFileWithFootersToDropBox(db, prefs, headers, lastKmsgFooter, + "/proc/last_kmsg", -LOG_SIZE, "SYSTEM_LAST_KMSG"); + addFileWithFootersToDropBox(db, prefs, headers, lastKmsgFooter, + "/sys/fs/pstore/console-ramoops", -LOG_SIZE, + "SYSTEM_LAST_KMSG"); + addFileToDropBox(db, prefs, headers, "/cache/recovery/log", + -LOG_SIZE, "SYSTEM_RECOVERY_LOG"); + addFileToDropBox(db, prefs, headers, "/data/dontpanic/apanic_console", + -LOG_SIZE, "APANIC_CONSOLE"); + addFileToDropBox(db, prefs, headers, "/data/dontpanic/apanic_threads", + -LOG_SIZE, "APANIC_THREADS"); + addAuditErrorsToDropBox(db, prefs, headers, -LOG_SIZE, "SYSTEM_AUDIT"); + addFsckErrorsToDropBox(db, prefs, headers, -LOG_SIZE, "SYSTEM_FSCK"); + } else { + if (db != null) db.addText("SYSTEM_RESTART", headers); + } + + // Scan existing tombstones (in case any new ones appeared) + File[] tombstoneFiles = TOMBSTONE_DIR.listFiles(); + for (int i = 0; tombstoneFiles != null && i < tombstoneFiles.length; i++) { + addFileToDropBox(db, prefs, headers, tombstoneFiles[i].getPath(), + LOG_SIZE, "SYSTEM_TOMBSTONE"); + } + + // Start watching for new tombstone files; will record them as they occur. + // This gets registered with the singleton file observer thread. + sTombstoneObserver = new FileObserver(TOMBSTONE_DIR.getPath(), FileObserver.CLOSE_WRITE) { + @Override + public void onEvent(int event, String path) { + try { + String filename = new File(TOMBSTONE_DIR, path).getPath(); + addFileToDropBox(db, prefs, headers, filename, LOG_SIZE, "SYSTEM_TOMBSTONE"); + } catch (IOException e) { + Slog.e(TAG, "Can't log tombstone", e); + } + } + }; + + sTombstoneObserver.startWatching(); + } + + private static void addFileToDropBox( + DropBoxManager db, SharedPreferences prefs, + String headers, String filename, int maxSize, String tag) throws IOException { + addFileWithFootersToDropBox(db, prefs, headers, "", filename, maxSize, + tag); + } + + private static void addFileWithFootersToDropBox( + DropBoxManager db, SharedPreferences prefs, + String headers, String footers, String filename, int maxSize, + String tag) throws IOException { + if (db == null || !db.isTagEnabled(tag)) return; // Logging disabled + + File file = new File(filename); + long fileTime = file.lastModified(); + if (fileTime <= 0) return; // File does not exist + + if (prefs != null) { + long lastTime = prefs.getLong(filename, 0); + if (lastTime == fileTime) return; // Already logged this particular file + // TODO: move all these SharedPreferences Editor commits + // outside this function to the end of logBootEvents + prefs.edit().putLong(filename, fileTime).apply(); + } + + Slog.i(TAG, "Copying " + filename + " to DropBox (" + tag + ")"); + db.addText(tag, headers + FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n") + footers); + } + + private static void addAuditErrorsToDropBox(DropBoxManager db, SharedPreferences prefs, + String headers, int maxSize, String tag) throws IOException { + if (db == null || !db.isTagEnabled(tag)) return; // Logging disabled + Slog.i(TAG, "Copying audit failures to DropBox"); + + File file = new File("/proc/last_kmsg"); + long fileTime = file.lastModified(); + if (fileTime <= 0) { + file = new File("/sys/fs/pstore/console-ramoops"); + fileTime = file.lastModified(); + } + + if (fileTime <= 0) return; // File does not exist + + if (prefs != null) { + long lastTime = prefs.getLong(tag, 0); + if (lastTime == fileTime) return; // Already logged this particular file + // TODO: move all these SharedPreferences Editor commits + // outside this function to the end of logBootEvents + prefs.edit().putLong(tag, fileTime).apply(); + } + + String log = FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n"); + StringBuilder sb = new StringBuilder(); + for (String line : log.split("\n")) { + if (line.contains("audit")) { + sb.append(line + "\n"); + } + } + Slog.i(TAG, "Copied " + sb.toString().length() + " worth of audits to DropBox"); + db.addText(tag, headers + sb.toString()); + } + + private static void addFsckErrorsToDropBox(DropBoxManager db, SharedPreferences prefs, + String headers, int maxSize, String tag) throws IOException { + boolean upload_needed = false; + if (db == null || !db.isTagEnabled(tag)) return; // Logging disabled + Slog.i(TAG, "Checking for fsck errors"); + + File file = new File("/dev/fscklogs/log"); + long fileTime = file.lastModified(); + if (fileTime <= 0) return; // File does not exist + + String log = FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n"); + StringBuilder sb = new StringBuilder(); + for (String line : log.split("\n")) { + if (line.contains("FILE SYSTEM WAS MODIFIED")) { + upload_needed = true; + break; + } + } + + if (upload_needed) { + addFileToDropBox(db, prefs, headers, "/dev/fscklogs/log", maxSize, tag); + } + + // Remove the file so we don't re-upload if the runtime restarts. + file.delete(); + } +} diff --git a/core/java/com/android/server/SystemService.java b/core/java/com/android/server/SystemService.java deleted file mode 100644 index 6e67970..0000000 --- a/core/java/com/android/server/SystemService.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (C) 2013 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.server; - -import android.content.Context; -import android.os.IBinder; -import android.os.ServiceManager; - -/** - * The base class for services running in the system process. Override and implement - * the lifecycle event callback methods as needed. - * <p> - * The lifecycle of a SystemService: - * </p><ul> - * <li>The constructor is called and provided with the system {@link Context} - * to initialize the system service. - * <li>{@link #onStart()} is called to get the service running. The service should - * publish its binder interface at this point using - * {@link #publishBinderService(String, IBinder)}. It may also publish additional - * local interfaces that other services within the system server may use to access - * privileged internal functions. - * <li>Then {@link #onBootPhase(int)} is called as many times as there are boot phases - * until {@link #PHASE_BOOT_COMPLETE} is sent, which is the last boot phase. Each phase - * is an opportunity to do special work, like acquiring optional service dependencies, - * waiting to see if SafeMode is enabled, or registering with a service that gets - * started after this one. - * </ul><p> - * NOTE: All lifecycle methods are called from the system server's main looper thread. - * </p> - * - * {@hide} - */ -public abstract class SystemService { - /* - * Boot Phases - */ - public static final int PHASE_WAIT_FOR_DEFAULT_DISPLAY = 100; // maybe should be a dependency? - - /** - * After receiving this boot phase, services can obtain lock settings data. - */ - public static final int PHASE_LOCK_SETTINGS_READY = 480; - - /** - * After receiving this boot phase, services can safely call into core system services - * such as the PowerManager or PackageManager. - */ - public static final int PHASE_SYSTEM_SERVICES_READY = 500; - - /** - * After receiving this boot phase, services can broadcast Intents. - */ - public static final int PHASE_ACTIVITY_MANAGER_READY = 550; - - /** - * After receiving this boot phase, services can start/bind to third party apps. - * Apps will be able to make Binder calls into services at this point. - */ - public static final int PHASE_THIRD_PARTY_APPS_CAN_START = 600; - - /** - * After receiving this boot phase, services can allow user interaction with the device. - * This phase occurs when boot has completed and the home application has started. - * System services may prefer to listen to this phase rather than registering a - * broadcast receiver for ACTION_BOOT_COMPLETED to reduce overall latency. - */ - public static final int PHASE_BOOT_COMPLETED = 1000; - - private final Context mContext; - - /** - * Initializes the system service. - * <p> - * Subclasses must define a single argument constructor that accepts the context - * and passes it to super. - * </p> - * - * @param context The system server context. - */ - public SystemService(Context context) { - mContext = context; - } - - /** - * Gets the system context. - */ - public final Context getContext() { - return mContext; - } - - /** - * Returns true if the system is running in safe mode. - * TODO: we should define in which phase this becomes valid - */ - public final boolean isSafeMode() { - return getManager().isSafeMode(); - } - - /** - * Called when the dependencies listed in the @Service class-annotation are available - * and after the chosen start phase. - * When this method returns, the service should be published. - */ - public abstract void onStart(); - - /** - * Called on each phase of the boot process. Phases before the service's start phase - * (as defined in the @Service annotation) are never received. - * - * @param phase The current boot phase. - */ - public void onBootPhase(int phase) {} - - /** - * Called when a new user is starting, for system services to initialize any per-user - * state they maintain for running users. - * @param userHandle The identifier of the user. - */ - public void onStartUser(int userHandle) {} - - /** - * Called when switching to a different foreground user, for system services that have - * special behavior for whichever user is currently in the foreground. This is called - * before any application processes are aware of the new user. - * @param userHandle The identifier of the user. - */ - public void onSwitchUser(int userHandle) {} - - /** - * Called when an existing user is stopping, for system services to finalize any per-user - * state they maintain for running users. This is called prior to sending the SHUTDOWN - * broadcast to the user; it is a good place to stop making use of any resources of that - * user (such as binding to a service running in the user). - * @param userHandle The identifier of the user. - */ - public void onStopUser(int userHandle) {} - - /** - * Called when an existing user is stopping, for system services to finalize any per-user - * state they maintain for running users. This is called after all application process - * teardown of the user is complete. - * @param userHandle The identifier of the user. - */ - public void onCleanupUser(int userHandle) {} - - /** - * Publish the service so it is accessible to other services and apps. - */ - protected final void publishBinderService(String name, IBinder service) { - publishBinderService(name, service, false); - } - - /** - * Publish the service so it is accessible to other services and apps. - */ - protected final void publishBinderService(String name, IBinder service, - boolean allowIsolated) { - ServiceManager.addService(name, service, allowIsolated); - } - - /** - * Get a binder service by its name. - */ - protected final IBinder getBinderService(String name) { - return ServiceManager.getService(name); - } - - /** - * Publish the service so it is only accessible to the system process. - */ - protected final <T> void publishLocalService(Class<T> type, T service) { - LocalServices.addService(type, service); - } - - /** - * Get a local service by interface. - */ - protected final <T> T getLocalService(Class<T> type) { - return LocalServices.getService(type); - } - - private SystemServiceManager getManager() { - return LocalServices.getService(SystemServiceManager.class); - } -} diff --git a/core/java/com/android/server/SystemServiceManager.java b/core/java/com/android/server/SystemServiceManager.java deleted file mode 100644 index fda6479..0000000 --- a/core/java/com/android/server/SystemServiceManager.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (C) 2013 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.server; - -import android.content.Context; -import android.util.Slog; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; - -/** - * Manages creating, starting, and other lifecycle events of - * {@link com.android.server.SystemService system services}. - * - * {@hide} - */ -public class SystemServiceManager { - private static final String TAG = "SystemServiceManager"; - - private final Context mContext; - private boolean mSafeMode; - - // Services that should receive lifecycle events. - private final ArrayList<SystemService> mServices = new ArrayList<SystemService>(); - - private int mCurrentPhase = -1; - - public SystemServiceManager(Context context) { - mContext = context; - } - - /** - * Starts a service by class name. - * - * @return The service instance. - */ - @SuppressWarnings("unchecked") - public SystemService startService(String className) { - final Class<SystemService> serviceClass; - try { - serviceClass = (Class<SystemService>)Class.forName(className); - } catch (ClassNotFoundException ex) { - Slog.i(TAG, "Starting " + className); - throw new RuntimeException("Failed to create service " + className - + ": service class not found, usually indicates that the caller should " - + "have called PackageManager.hasSystemFeature() to check whether the " - + "feature is available on this device before trying to start the " - + "services that implement it", ex); - } - return startService(serviceClass); - } - - /** - * Creates and starts a system service. The class must be a subclass of - * {@link com.android.server.SystemService}. - * - * @param serviceClass A Java class that implements the SystemService interface. - * @return The service instance, never null. - * @throws RuntimeException if the service fails to start. - */ - @SuppressWarnings("unchecked") - public <T extends SystemService> T startService(Class<T> serviceClass) { - final String name = serviceClass.getName(); - Slog.i(TAG, "Starting " + name); - - // Create the service. - if (!SystemService.class.isAssignableFrom(serviceClass)) { - throw new RuntimeException("Failed to create " + name - + ": service must extend " + SystemService.class.getName()); - } - final T service; - try { - Constructor<T> constructor = serviceClass.getConstructor(Context.class); - service = constructor.newInstance(mContext); - } catch (InstantiationException ex) { - throw new RuntimeException("Failed to create service " + name - + ": service could not be instantiated", ex); - } catch (IllegalAccessException ex) { - throw new RuntimeException("Failed to create service " + name - + ": service must have a public constructor with a Context argument", ex); - } catch (NoSuchMethodException ex) { - throw new RuntimeException("Failed to create service " + name - + ": service must have a public constructor with a Context argument", ex); - } catch (InvocationTargetException ex) { - throw new RuntimeException("Failed to create service " + name - + ": service constructor threw an exception", ex); - } - - // Register it. - mServices.add(service); - - // Start it. - try { - service.onStart(); - } catch (RuntimeException ex) { - throw new RuntimeException("Failed to start service " + name - + ": onStart threw an exception", ex); - } - return service; - } - - /** - * Starts the specified boot phase for all system services that have been started up to - * this point. - * - * @param phase The boot phase to start. - */ - public void startBootPhase(final int phase) { - if (phase <= mCurrentPhase) { - throw new IllegalArgumentException("Next phase must be larger than previous"); - } - mCurrentPhase = phase; - - Slog.i(TAG, "Starting phase " + mCurrentPhase); - - final int serviceLen = mServices.size(); - for (int i = 0; i < serviceLen; i++) { - final SystemService service = mServices.get(i); - try { - service.onBootPhase(mCurrentPhase); - } catch (Exception ex) { - throw new RuntimeException("Failed to boot service " - + service.getClass().getName() - + ": onBootPhase threw an exception during phase " - + mCurrentPhase, ex); - } - } - } - - public void startUser(final int userHandle) { - final int serviceLen = mServices.size(); - for (int i = 0; i < serviceLen; i++) { - final SystemService service = mServices.get(i); - try { - service.onStartUser(userHandle); - } catch (Exception ex) { - Slog.wtf(TAG, "Failure reporting start of user " + userHandle - + " to service " + service.getClass().getName(), ex); - } - } - } - - public void switchUser(final int userHandle) { - final int serviceLen = mServices.size(); - for (int i = 0; i < serviceLen; i++) { - final SystemService service = mServices.get(i); - try { - service.onSwitchUser(userHandle); - } catch (Exception ex) { - Slog.wtf(TAG, "Failure reporting switch of user " + userHandle - + " to service " + service.getClass().getName(), ex); - } - } - } - - public void stopUser(final int userHandle) { - final int serviceLen = mServices.size(); - for (int i = 0; i < serviceLen; i++) { - final SystemService service = mServices.get(i); - try { - service.onStopUser(userHandle); - } catch (Exception ex) { - Slog.wtf(TAG, "Failure reporting stop of user " + userHandle - + " to service " + service.getClass().getName(), ex); - } - } - } - - public void cleanupUser(final int userHandle) { - final int serviceLen = mServices.size(); - for (int i = 0; i < serviceLen; i++) { - final SystemService service = mServices.get(i); - try { - service.onCleanupUser(userHandle); - } catch (Exception ex) { - Slog.wtf(TAG, "Failure reporting cleanup of user " + userHandle - + " to service " + service.getClass().getName(), ex); - } - } - } - - /** Sets the safe mode flag for services to query. */ - public void setSafeMode(boolean safeMode) { - mSafeMode = safeMode; - } - - /** - * Returns whether we are booting into safe mode. - * @return safe mode flag - */ - public boolean isSafeMode() { - return mSafeMode; - } - - /** - * Outputs the state of this manager to the System log. - */ - public void dump() { - StringBuilder builder = new StringBuilder(); - builder.append("Current phase: ").append(mCurrentPhase).append("\n"); - builder.append("Services:\n"); - final int startedLen = mServices.size(); - for (int i = 0; i < startedLen; i++) { - final SystemService service = mServices.get(i); - builder.append("\t") - .append(service.getClass().getSimpleName()) - .append("\n"); - } - - Slog.e(TAG, builder.toString()); - } -} 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_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), |