diff options
Diffstat (limited to 'core/java/com')
8 files changed, 144 insertions, 416 deletions
diff --git a/core/java/com/android/internal/app/ExternalMediaFormatActivity.java b/core/java/com/android/internal/app/ExternalMediaFormatActivity.java index 6ed3bdc..fc213c5 100644 --- a/core/java/com/android/internal/app/ExternalMediaFormatActivity.java +++ b/core/java/com/android/internal/app/ExternalMediaFormatActivity.java @@ -25,6 +25,7 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; +import android.os.storage.StorageVolume; import android.util.Log; /** @@ -94,6 +95,10 @@ public class ExternalMediaFormatActivity extends AlertActivity implements Dialog if (which == POSITIVE_BUTTON) { Intent intent = new Intent(ExternalStorageFormatter.FORMAT_ONLY); intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME); + // Transfer the storage volume to the new intent + final StorageVolume storageVolume = getIntent().getParcelableExtra( + StorageVolume.EXTRA_STORAGE_VOLUME); + intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, storageVolume); startService(intent); } diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java index 3301cbe..34ae58a 100644 --- a/core/java/com/android/internal/os/WrapperInit.java +++ b/core/java/com/android/internal/os/WrapperInit.java @@ -19,6 +19,7 @@ package com.android.internal.os; import android.os.Process; import android.util.Slog; +import dalvik.system.VMRuntime; import java.io.DataOutputStream; import java.io.FileDescriptor; import java.io.FileOutputStream; @@ -62,7 +63,8 @@ public class WrapperInit { // wrapper that it directly forked). if (fdNum != 0) { try { - FileDescriptor fd = ZygoteInit.createFileDescriptor(fdNum); + FileDescriptor fd = new FileDescriptor(); + fd.setInt$(fdNum); DataOutputStream os = new DataOutputStream(new FileOutputStream(fd)); os.writeInt(Process.myPid()); os.close(); @@ -95,9 +97,20 @@ public class WrapperInit { * @param args Arguments for {@link RuntimeInit#main}. */ public static void execApplication(String invokeWith, String niceName, - int targetSdkVersion, FileDescriptor pipeFd, String[] args) { + int targetSdkVersion, String instructionSet, FileDescriptor pipeFd, + String[] args) { StringBuilder command = new StringBuilder(invokeWith); - command.append(" /system/bin/app_process /system/bin --application"); + + final String appProcess; + if (VMRuntime.is64BitInstructionSet(instructionSet)) { + appProcess = "/system/bin/app_process64"; + } else { + appProcess = "/system/bin/app_process32"; + } + command.append(' '); + command.append(appProcess); + + command.append(" /system/bin --application"); if (niceName != null) { command.append(" '--nice-name=").append(niceName).append("'"); } diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index cca340c..fced092 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -20,12 +20,9 @@ package com.android.internal.os; import dalvik.system.ZygoteHooks; import android.system.ErrnoException; import android.system.Os; -import android.os.SystemClock; -import android.util.Slog; /** @hide */ public final class Zygote { - private static final String TAG = "Zygote"; /* * Bit values for "debugFlags" argument. The definitions are duplicated * in the native code. @@ -87,15 +84,11 @@ public final class Zygote { public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, String instructionSet, String appDataDir) { - long startTime = SystemClock.elapsedRealtime(); VM_HOOKS.preFork(); - checkTime(startTime, "Zygote.preFork"); int pid = nativeForkAndSpecialize( uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, instructionSet, appDataDir); - checkTime(startTime, "Zygote.nativeForkAndSpecialize"); VM_HOOKS.postForkCommon(); - checkTime(startTime, "Zygote.postForkCommon"); return pid; } @@ -104,18 +97,6 @@ public final class Zygote { String instructionSet, String appDataDir); /** - * Temporary hack: check time since start time and log if over a fixed threshold. - * - */ - private static void checkTime(long startTime, String where) { - long now = SystemClock.elapsedRealtime(); - if ((now-startTime) > 1000) { - // If we are taking more than a second, log about it. - Slog.w(TAG, "Slow operation: " + (now-startTime) + "ms so far, now at " + where); - } - } - - /** * Special method to start the system server process. In addition to the * common actions performed in forkAndSpecialize, the pid of the child * process is recorded such that the death of the child process will cause @@ -151,9 +132,7 @@ public final class Zygote { int[][] rlimits, long permittedCapabilities, long effectiveCapabilities); private static void callPostForkChildHooks(int debugFlags, String instructionSet) { - long startTime = SystemClock.elapsedRealtime(); VM_HOOKS.postForkChild(debugFlags, instructionSet); - checkTime(startTime, "Zygote.callPostForkChildHooks"); } diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index 2ef8a20..aba4bd0 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -16,6 +16,12 @@ package com.android.internal.os; +import static android.system.OsConstants.F_SETFD; +import static android.system.OsConstants.O_CLOEXEC; +import static android.system.OsConstants.STDERR_FILENO; +import static android.system.OsConstants.STDIN_FILENO; +import static android.system.OsConstants.STDOUT_FILENO; + import android.net.Credentials; import android.net.LocalSocket; import android.os.Process; @@ -25,6 +31,7 @@ import android.system.ErrnoException; import android.system.Os; import android.util.Log; import dalvik.system.PathClassLoader; +import dalvik.system.VMRuntime; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -37,8 +44,6 @@ import java.io.PrintStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import libcore.io.IoUtils; -import android.os.SystemClock; -import android.util.Slog; /** * A connection that can make spawn requests. @@ -93,7 +98,7 @@ class ZygoteConnection { new InputStreamReader(socket.getInputStream()), 256); mSocket.setSoTimeout(CONNECTION_TIMEOUT_MILLIS); - + try { peer = mSocket.getPeerCredentials(); } catch (IOException ex) { @@ -105,23 +110,11 @@ class ZygoteConnection { } /** - * Temporary hack: check time since start time and log if over a fixed threshold. - * - */ - private void checkTime(long startTime, String where) { - long now = SystemClock.elapsedRealtime(); - if ((now-startTime) > 1000) { - // If we are taking more than a second, log about it. - Slog.w(TAG, "Slow operation: " + (now-startTime) + "ms so far, now at " + where); - } - } - - /** * Returns the file descriptor of the associated socket. * * @return null-ok; file descriptor */ - FileDescriptor getFileDescriptor() { + FileDescriptor getFileDesciptor() { return mSocket.getFileDescriptor(); } @@ -145,8 +138,6 @@ class ZygoteConnection { Arguments parsedArgs = null; FileDescriptor[] descriptors; - long startTime = SystemClock.elapsedRealtime(); - try { args = readArgumentList(); descriptors = mSocket.getAncillaryFileDescriptors(); @@ -156,7 +147,6 @@ class ZygoteConnection { return true; } - checkTime(startTime, "zygoteConnection.runOnce: readArgumentList"); if (args == null) { // EOF reached. closeSocket(); @@ -188,30 +178,25 @@ class ZygoteConnection { ", effective=0x" + Long.toHexString(parsedArgs.effectiveCapabilities)); } - applyUidSecurityPolicy(parsedArgs, peer, peerSecurityContext); applyRlimitSecurityPolicy(parsedArgs, peer, peerSecurityContext); applyInvokeWithSecurityPolicy(parsedArgs, peer, peerSecurityContext); applyseInfoSecurityPolicy(parsedArgs, peer, peerSecurityContext); - checkTime(startTime, "zygoteConnection.runOnce: apply security policies"); - applyDebuggerSystemProperty(parsedArgs); applyInvokeWithSystemProperty(parsedArgs); - checkTime(startTime, "zygoteConnection.runOnce: apply security policies"); - int[][] rlimits = null; if (parsedArgs.rlimits != null) { rlimits = parsedArgs.rlimits.toArray(intArray2d); } - if (parsedArgs.runtimeInit && parsedArgs.invokeWith != null) { - FileDescriptor[] pipeFds = Os.pipe(); + if (parsedArgs.invokeWith != null) { + FileDescriptor[] pipeFds = Os.pipe2(O_CLOEXEC); childPipeFd = pipeFds[1]; serverPipeFd = pipeFds[0]; - ZygoteInit.setCloseOnExec(serverPipeFd, true); + Os.fcntlInt(childPipeFd, F_SETFD, 0); } /** @@ -242,14 +227,10 @@ class ZygoteConnection { fd = null; - checkTime(startTime, "zygoteConnection.runOnce: preForkAndSpecialize"); pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet, parsedArgs.appDataDir); - checkTime(startTime, "zygoteConnection.runOnce: postForkAndSpecialize"); - } catch (IOException ex) { - logAndPrintError(newStderr, "Exception creating pipe", ex); } catch (ErrnoException ex) { logAndPrintError(newStderr, "Exception creating pipe", ex); } catch (IllegalArgumentException ex) { @@ -323,20 +304,13 @@ class ZygoteConnection { * <li> --rlimit=r,c,m<i>tuple of values for setrlimit() call. * <code>r</code> is the resource, <code>c</code> and <code>m</code> * are the settings for current and max value.</i> - * <li> --classpath=<i>colon-separated classpath</i> indicates - * that the specified class (which must b first non-flag argument) should - * be loaded from jar files in the specified classpath. Incompatible with - * --runtime-init - * <li> --runtime-init indicates that the remaining arg list should + * <li> --instruction-set=<i>instruction-set-string</i> which instruction set to use/emulate. + * <li> --nice-name=<i>nice name to appear in ps</i> + * <li> --runtime-args indicates that the remaining arg list should * be handed off to com.android.internal.os.RuntimeInit, rather than - * processed directly + * processed directly. * Android runtime startup (eg, Binder initialization) is also eschewed. - * <li> --nice-name=<i>nice name to appear in ps</i> - * <li> If <code>--runtime-init</code> is present: - * [--] <args for RuntimeInit > - * <li> If <code>--runtime-init</code> is absent: - * [--] <classname> [args...] - * <li> --instruction-set=<i>instruction-set-string</i> which instruction set to use/emulate. + * <li> [--] <args for RuntimeInit > * </ul> */ static class Arguments { @@ -364,12 +338,6 @@ class ZygoteConnection { int targetSdkVersion; boolean targetSdkVersionSpecified; - /** from --classpath */ - String classpath; - - /** from --runtime-init */ - boolean runtimeInit; - /** from --nice-name */ String niceName; @@ -431,6 +399,8 @@ class ZygoteConnection { throws IllegalArgumentException { int curArg = 0; + boolean seenRuntimeArgs = true; + for ( /* curArg */ ; curArg < args.length; curArg++) { String arg = args[curArg]; @@ -471,8 +441,8 @@ class ZygoteConnection { debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING; } else if (arg.equals("--enable-assert")) { debugFlags |= Zygote.DEBUG_ENABLE_ASSERT; - } else if (arg.equals("--runtime-init")) { - runtimeInit = true; + } else if (arg.equals("--runtime-args")) { + seenRuntimeArgs = true; } else if (arg.startsWith("--seinfo=")) { if (seInfoSpecified) { throw new IllegalArgumentException( @@ -517,17 +487,6 @@ class ZygoteConnection { } rlimits.add(rlimitTuple); - } else if (arg.equals("-classpath")) { - if (classpath != null) { - throw new IllegalArgumentException( - "Duplicate arg specified"); - } - try { - classpath = args[++curArg]; - } catch (IndexOutOfBoundsException ex) { - throw new IllegalArgumentException( - "-classpath requires argument"); - } } else if (arg.startsWith("--setgroups=")) { if (gids != null) { throw new IllegalArgumentException( @@ -574,9 +533,8 @@ class ZygoteConnection { } } - if (runtimeInit && classpath != null) { - throw new IllegalArgumentException( - "--runtime-init and -classpath are incompatible"); + if (!seenRuntimeArgs) { + throw new IllegalArgumentException("Unexpected argument : " + args[curArg]); } remainingArgs = new String[args.length - curArg]; @@ -620,7 +578,7 @@ class ZygoteConnection { } // See bug 1092107: large argc can be used for a DOS attack - if (argc > MAX_ZYGOTE_ARGC) { + if (argc > MAX_ZYGOTE_ARGC) { throw new IOException("max arg count exceeded"); } @@ -637,7 +595,7 @@ class ZygoteConnection { } /** - * Applies zygote security policy per bugs #875058 and #1082165. + * Applies zygote security policy per bugs #875058 and #1082165. * Based on the credentials of the process issuing a zygote command: * <ol> * <li> uid 0 (root) may specify any uid, gid, and setgroups() list @@ -668,7 +626,7 @@ class ZygoteConnection { /* In normal operation, SYSTEM_UID can only specify a restricted * set of UIDs. In factory test mode, SYSTEM_UID may specify any uid. */ - uidRestricted + uidRestricted = !(factoryTest.equals("1") || factoryTest.equals("2")); if (uidRestricted @@ -881,14 +839,15 @@ class ZygoteConnection { if (descriptors != null) { try { - ZygoteInit.reopenStdio(descriptors[0], - descriptors[1], descriptors[2]); + Os.dup2(descriptors[0], STDIN_FILENO); + Os.dup2(descriptors[1], STDOUT_FILENO); + Os.dup2(descriptors[2], STDERR_FILENO); for (FileDescriptor fd: descriptors) { IoUtils.closeQuietly(fd); } newStderr = System.err; - } catch (IOException ex) { + } catch (ErrnoException ex) { Log.e(TAG, "Error reopening stdio", ex); } } @@ -897,47 +856,14 @@ class ZygoteConnection { Process.setArgV0(parsedArgs.niceName); } - if (parsedArgs.runtimeInit) { - if (parsedArgs.invokeWith != null) { - WrapperInit.execApplication(parsedArgs.invokeWith, - parsedArgs.niceName, parsedArgs.targetSdkVersion, - pipeFd, parsedArgs.remainingArgs); - } else { - RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, - parsedArgs.remainingArgs, null /* classLoader */); - } + if (parsedArgs.invokeWith != null) { + WrapperInit.execApplication(parsedArgs.invokeWith, + parsedArgs.niceName, parsedArgs.targetSdkVersion, + VMRuntime.getCurrentInstructionSet(), + pipeFd, parsedArgs.remainingArgs); } else { - String className; - try { - className = parsedArgs.remainingArgs[0]; - } catch (ArrayIndexOutOfBoundsException ex) { - logAndPrintError(newStderr, - "Missing required class name argument", null); - return; - } - - String[] mainArgs = new String[parsedArgs.remainingArgs.length - 1]; - System.arraycopy(parsedArgs.remainingArgs, 1, - mainArgs, 0, mainArgs.length); - - if (parsedArgs.invokeWith != null) { - WrapperInit.execStandalone(parsedArgs.invokeWith, - parsedArgs.classpath, className, mainArgs); - } else { - ClassLoader cloader; - if (parsedArgs.classpath != null) { - cloader = new PathClassLoader(parsedArgs.classpath, - ClassLoader.getSystemClassLoader()); - } else { - cloader = ClassLoader.getSystemClassLoader(); - } - - try { - ZygoteInit.invokeStaticMain(cloader, className, mainArgs); - } catch (RuntimeException ex) { - logAndPrintError(newStderr, "Error starting.", ex); - } - } + RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, + parsedArgs.remainingArgs, null /* classLoader */); } } @@ -1014,8 +940,8 @@ class ZygoteConnection { private void setChildPgid(int pid) { // Try to move the new child into the peer's process group. try { - ZygoteInit.setpgid(pid, ZygoteInit.getpgid(peer.getPid())); - } catch (IOException ex) { + Os.setpgid(pid, Os.getpgid(peer.getPid())); + } catch (ErrnoException ex) { // This exception is expected in the case where // the peer is not in our session // TODO get rid of this log message in the case where diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index d95cf71..8107985 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -16,6 +16,7 @@ package com.android.internal.os; +import static android.system.OsConstants.POLLIN; import static android.system.OsConstants.S_IRWXG; import static android.system.OsConstants.S_IRWXO; @@ -32,6 +33,7 @@ import android.os.Trace; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; +import android.system.StructPollfd; import android.util.EventLog; import android.util.Log; import android.util.Slog; @@ -93,12 +95,6 @@ public class ZygoteInit { private static Resources mResources; /** - * The number of times that the main Zygote loop - * should run before calling gc() again. - */ - static final int GC_LOOP_COUNT = 10; - - /** * The path of a file that contains classes to preload. */ private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes"; @@ -107,54 +103,6 @@ public class ZygoteInit { private static final boolean PRELOAD_RESOURCES = true; /** - * Invokes a static "main(argv[]) method on class "className". - * Converts various failing exceptions into RuntimeExceptions, with - * the assumption that they will then cause the VM instance to exit. - * - * @param loader class loader to use - * @param className Fully-qualified class name - * @param argv Argument vector for main() - */ - static void invokeStaticMain(ClassLoader loader, - String className, String[] argv) - throws ZygoteInit.MethodAndArgsCaller { - Class<?> cl; - - try { - cl = loader.loadClass(className); - } catch (ClassNotFoundException ex) { - throw new RuntimeException( - "Missing class when invoking static main " + className, - ex); - } - - Method m; - try { - m = cl.getMethod("main", new Class[] { String[].class }); - } catch (NoSuchMethodException ex) { - throw new RuntimeException( - "Missing static main on " + className, ex); - } catch (SecurityException ex) { - throw new RuntimeException( - "Problem getting static main on " + className, ex); - } - - int modifiers = m.getModifiers(); - if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) { - throw new RuntimeException( - "Main method is not public and static on " + className); - } - - /* - * This throw gets caught in ZygoteInit.main(), which responds - * by invoking the exception's run() method. This arrangement - * clears up all the stack frames that were required in setting - * up the process. - */ - throw new ZygoteInit.MethodAndArgsCaller(m, argv); - } - - /** * Registers a server socket for zygote command connections * * @throws RuntimeException when open fails @@ -171,8 +119,9 @@ public class ZygoteInit { } try { - sServerSocket = new LocalServerSocket( - createFileDescriptor(fileDesc)); + FileDescriptor fd = new FileDescriptor(); + fd.setInt$(fileDesc); + sServerSocket = new LocalServerSocket(fd); } catch (IOException ex) { throw new RuntimeException( "Error binding to local socket '" + fileDesc + "'", ex); @@ -231,26 +180,6 @@ public class ZygoteInit { private static final int ROOT_UID = 0; private static final int ROOT_GID = 0; - /** - * Sets effective user ID. - */ - private static void setEffectiveUser(int uid) { - int errno = setreuid(ROOT_UID, uid); - if (errno != 0) { - Log.e(TAG, "setreuid() failed. errno: " + errno); - } - } - - /** - * Sets effective group ID. - */ - private static void setEffectiveGroup(int gid) { - int errno = setregid(ROOT_GID, gid); - if (errno != 0) { - Log.e(TAG, "setregid() failed. errno: " + errno); - } - } - static void preload() { Log.d(TAG, "begin preload"); preloadClasses(); @@ -298,19 +227,29 @@ public class ZygoteInit { long startTime = SystemClock.uptimeMillis(); // Drop root perms while running static initializers. - setEffectiveGroup(UNPRIVILEGED_GID); - setEffectiveUser(UNPRIVILEGED_UID); + final int reuid = Os.getuid(); + final int regid = Os.getgid(); + + // We need to drop root perms only if we're already root. In the case of "wrapped" + // processes (see WrapperInit), this function is called from an unprivileged uid + // and gid. + boolean droppedPriviliges = false; + if (reuid == ROOT_UID && regid == ROOT_GID) { + try { + Os.setregid(ROOT_GID, UNPRIVILEGED_GID); + Os.setreuid(ROOT_UID, UNPRIVILEGED_UID); + } catch (ErrnoException ex) { + throw new RuntimeException("Failed to drop root", ex); + } + + droppedPriviliges = true; + } // Alter the target heap utilization. With explicit GCs this // is not likely to have any effect. float defaultUtilization = runtime.getTargetHeapUtilization(); runtime.setTargetHeapUtilization(0.8f); - // Start with a clean slate. - System.gc(); - runtime.runFinalizationSync(); - Debug.startAllocCounting(); - try { BufferedReader br = new BufferedReader(new InputStreamReader(is), 256); @@ -329,15 +268,6 @@ public class ZygoteInit { Log.v(TAG, "Preloading " + line + "..."); } Class.forName(line); - if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) { - if (false) { - Log.v(TAG, - " GC at " + Debug.getGlobalAllocSize()); - } - System.gc(); - runtime.runFinalizationSync(); - Debug.resetGlobalAllocSize(); - } count++; } catch (ClassNotFoundException e) { Log.w(TAG, "Class not found for preloading: " + line); @@ -367,11 +297,15 @@ public class ZygoteInit { // Fill in dex caches with classes, fields, and methods brought in by preloading. runtime.preloadDexCaches(); - Debug.stopAllocCounting(); - - // Bring back root. We'll need it later. - setEffectiveUser(ROOT_UID); - setEffectiveGroup(ROOT_GID); + // Bring back root. We'll need it later if we're in the zygote. + if (droppedPriviliges) { + try { + Os.setreuid(ROOT_UID, ROOT_UID); + Os.setregid(ROOT_GID, ROOT_GID); + } catch (ErrnoException ex) { + throw new RuntimeException("Failed to restore root", ex); + } + } } } @@ -385,10 +319,7 @@ public class ZygoteInit { private static void preloadResources() { final VMRuntime runtime = VMRuntime.getRuntime(); - Debug.startAllocCounting(); try { - System.gc(); - runtime.runFinalizationSync(); mResources = Resources.getSystem(); mResources.startPreloading(); if (PRELOAD_RESOURCES) { @@ -413,22 +344,12 @@ public class ZygoteInit { mResources.finishPreloading(); } catch (RuntimeException e) { Log.w(TAG, "Failure preloading resources", e); - } finally { - Debug.stopAllocCounting(); } } private static int preloadColorStateLists(VMRuntime runtime, TypedArray ar) { int N = ar.length(); for (int i=0; i<N; i++) { - if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) { - if (false) { - Log.v(TAG, " GC at " + Debug.getGlobalAllocSize()); - } - System.gc(); - runtime.runFinalizationSync(); - Debug.resetGlobalAllocSize(); - } int id = ar.getResourceId(i, 0); if (false) { Log.v(TAG, "Preloading resource #" + Integer.toHexString(id)); @@ -449,14 +370,6 @@ public class ZygoteInit { private static int preloadDrawables(VMRuntime runtime, TypedArray ar) { int N = ar.length(); for (int i=0; i<N; i++) { - if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) { - if (false) { - Log.v(TAG, " GC at " + Debug.getGlobalAllocSize()); - } - System.gc(); - runtime.runFinalizationSync(); - Debug.resetGlobalAllocSize(); - } int id = ar.getResourceId(i, 0); if (false) { Log.v(TAG, "Preloading resource #" + Integer.toHexString(id)); @@ -478,7 +391,7 @@ public class ZygoteInit { * softly- and final-reachable objects, along with any other garbage. * This is only useful just before a fork(). */ - /*package*/ static void gc() { + /*package*/ static void gcAndFinalize() { final VMRuntime runtime = VMRuntime.getRuntime(); /* runFinalizationSync() lets finalizers be called in Zygote, @@ -487,9 +400,6 @@ public class ZygoteInit { System.gc(); runtime.runFinalizationSync(); System.gc(); - runtime.runFinalizationSync(); - System.gc(); - runtime.runFinalizationSync(); } /** @@ -527,7 +437,7 @@ public class ZygoteInit { WrapperInit.execApplication(parsedArgs.invokeWith, parsedArgs.niceName, parsedArgs.targetSdkVersion, - null, args); + VMRuntime.getCurrentInstructionSet(), null, args); } else { ClassLoader cl = null; if (systemServerClasspath != null) { @@ -680,7 +590,7 @@ public class ZygoteInit { SamplingProfilerIntegration.writeZygoteSnapshot(); // Do an initial gc to clean up after startup - gc(); + gcAndFinalize(); // Disable tracing so that forked processes do not inherit stale tracing tags from // Zygote. @@ -744,137 +654,42 @@ public class ZygoteInit { private static void runSelectLoop(String abiList) throws MethodAndArgsCaller { ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>(); ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>(); - FileDescriptor[] fdArray = new FileDescriptor[4]; fds.add(sServerSocket.getFileDescriptor()); peers.add(null); - int loopCount = GC_LOOP_COUNT; while (true) { - int index; - - /* - * Call gc() before we block in select(). - * It's work that has to be done anyway, and it's better - * to avoid making every child do it. It will also - * madvise() any free memory as a side-effect. - * - * Don't call it every time, because walking the entire - * heap is a lot of overhead to free a few hundred bytes. - */ - if (loopCount <= 0) { - gc(); - loopCount = GC_LOOP_COUNT; - } else { - loopCount--; + StructPollfd[] pollFds = new StructPollfd[fds.size()]; + for (int i = 0; i < pollFds.length; ++i) { + pollFds[i] = new StructPollfd(); + pollFds[i].fd = fds.get(i); + pollFds[i].events = (short) POLLIN; } - - try { - fdArray = fds.toArray(fdArray); - index = selectReadable(fdArray); - } catch (IOException ex) { - throw new RuntimeException("Error in select()", ex); + Os.poll(pollFds, -1); + } catch (ErrnoException ex) { + throw new RuntimeException("poll failed", ex); } - - if (index < 0) { - throw new RuntimeException("Error in select()"); - } else if (index == 0) { - ZygoteConnection newPeer = acceptCommandPeer(abiList); - peers.add(newPeer); - fds.add(newPeer.getFileDescriptor()); - } else { - boolean done; - done = peers.get(index).runOnce(); - - if (done) { - peers.remove(index); - fds.remove(index); + for (int i = pollFds.length - 1; i >= 0; --i) { + if ((pollFds[i].revents & POLLIN) == 0) { + continue; + } + if (i == 0) { + ZygoteConnection newPeer = acceptCommandPeer(abiList); + peers.add(newPeer); + fds.add(newPeer.getFileDesciptor()); + } else { + boolean done = peers.get(i).runOnce(); + if (done) { + peers.remove(i); + fds.remove(i); + } } } } } /** - * The Linux syscall "setreuid()" - * @param ruid real uid - * @param euid effective uid - * @return 0 on success, non-zero errno on fail - */ - static native int setreuid(int ruid, int euid); - - /** - * The Linux syscall "setregid()" - * @param rgid real gid - * @param egid effective gid - * @return 0 on success, non-zero errno on fail - */ - static native int setregid(int rgid, int egid); - - /** - * Invokes the linux syscall "setpgid" - * - * @param pid pid to change - * @param pgid new process group of pid - * @return 0 on success or non-zero errno on fail - */ - static native int setpgid(int pid, int pgid); - - /** - * Invokes the linux syscall "getpgid" - * - * @param pid pid to query - * @return pgid of pid in question - * @throws IOException on error - */ - static native int getpgid(int pid) throws IOException; - - /** - * Invokes the syscall dup2() to copy the specified descriptors into - * stdin, stdout, and stderr. The existing stdio descriptors will be - * closed and errors during close will be ignored. The specified - * descriptors will also remain open at their original descriptor numbers, - * so the caller may want to close the original descriptors. - * - * @param in new stdin - * @param out new stdout - * @param err new stderr - * @throws IOException - */ - static native void reopenStdio(FileDescriptor in, - FileDescriptor out, FileDescriptor err) throws IOException; - - /** - * Toggles the close-on-exec flag for the specified file descriptor. - * - * @param fd non-null; file descriptor - * @param flag desired close-on-exec flag state - * @throws IOException - */ - static native void setCloseOnExec(FileDescriptor fd, boolean flag) - throws IOException; - - /** - * Invokes select() on the provider array of file descriptors (selecting - * for readability only). Array elements of null are ignored. - * - * @param fds non-null; array of readable file descriptors - * @return index of descriptor that is now readable or -1 for empty array. - * @throws IOException if an error occurs - */ - static native int selectReadable(FileDescriptor[] fds) throws IOException; - - /** - * Creates a file descriptor from an int fd. - * - * @param fd integer OS file descriptor - * @return non-null; FileDescriptor instance - * @throws IOException if fd is invalid - */ - static native FileDescriptor createFileDescriptor(int fd) - throws IOException; - - /** * Class not instantiable. */ private ZygoteInit() { diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index f6c42af..0afc651 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -48,6 +48,9 @@ import android.widget.Button; import com.android.internal.R; import com.google.android.collect.Lists; +import java.io.ByteArrayOutputStream; +import java.nio.charset.StandardCharsets; +import libcore.util.HexEncoding; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -357,7 +360,7 @@ public class LockPatternUtils { */ public boolean checkPasswordHistory(String password) { String passwordHashString = new String( - passwordToHash(password, getCurrentOrCallingUserId())); + passwordToHash(password, getCurrentOrCallingUserId()), StandardCharsets.UTF_8); String passwordHistory = getString(PASSWORD_HISTORY_KEY); if (passwordHistory == null) { return false; @@ -889,7 +892,7 @@ public class LockPatternUtils { passwordHistory = ""; } else { byte[] hash = passwordToHash(password, userHandle); - passwordHistory = new String(hash) + "," + passwordHistory; + passwordHistory = new String(hash, StandardCharsets.UTF_8) + "," + passwordHistory; // Cut it to contain passwordHistoryLength hashes // and passwordHistoryLength -1 commas. passwordHistory = passwordHistory.substring(0, Math.min(hash.length @@ -1076,34 +1079,30 @@ public class LockPatternUtils { * Generate a hash for the given password. To avoid brute force attacks, we use a salted hash. * Not the most secure, but it is at least a second level of protection. First level is that * the file is in a location only readable by the system process. + * * @param password the gesture pattern. + * * @return the hash of the pattern in a byte array. */ public byte[] passwordToHash(String password, int userId) { if (password == null) { return null; } - String algo = null; - byte[] hashed = null; + try { byte[] saltedPassword = (password + getSalt(userId)).getBytes(); - byte[] sha1 = MessageDigest.getInstance(algo = "SHA-1").digest(saltedPassword); - byte[] md5 = MessageDigest.getInstance(algo = "MD5").digest(saltedPassword); - hashed = (toHex(sha1) + toHex(md5)).getBytes(); - } catch (NoSuchAlgorithmException e) { - Log.w(TAG, "Failed to encode string because of missing algorithm: " + algo); - } - return hashed; - } + byte[] sha1 = MessageDigest.getInstance("SHA-1").digest(saltedPassword); + byte[] md5 = MessageDigest.getInstance("MD5").digest(saltedPassword); - private static String toHex(byte[] ary) { - final String hex = "0123456789ABCDEF"; - String ret = ""; - for (int i = 0; i < ary.length; i++) { - ret += hex.charAt((ary[i] >> 4) & 0xf); - ret += hex.charAt(ary[i] & 0xf); + byte[] combined = new byte[sha1.length + md5.length]; + System.arraycopy(sha1, 0, combined, 0, sha1.length); + System.arraycopy(md5, 0, combined, sha1.length, md5.length); + + final char[] hexEncoded = HexEncoding.encode(combined); + return new String(hexEncoded).getBytes(StandardCharsets.UTF_8); + } catch (NoSuchAlgorithmException e) { + throw new AssertionError("Missing digest algorithm: ", e); } - return ret; } /** diff --git a/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java b/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java index b680fab..11ac19e 100644 --- a/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java +++ b/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java @@ -863,7 +863,7 @@ public class GlowPadView extends View { // tx and ty are relative to wave center float tx = eventX - mWaveCenterX; float ty = eventY - mWaveCenterY; - float touchRadius = (float) Math.sqrt(dist2(tx, ty)); + float touchRadius = (float) Math.hypot(tx, ty); final float scale = touchRadius > mOuterRadius ? mOuterRadius / touchRadius : 1.0f; float limitX = tx * scale; float limitY = ty * scale; diff --git a/core/java/com/android/internal/widget/multiwaveview/PointCloud.java b/core/java/com/android/internal/widget/multiwaveview/PointCloud.java index f299935..6f26b99 100644 --- a/core/java/com/android/internal/widget/multiwaveview/PointCloud.java +++ b/core/java/com/android/internal/widget/multiwaveview/PointCloud.java @@ -22,7 +22,6 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.drawable.Drawable; -import android.util.FloatMath; import android.util.Log; public class PointCloud { @@ -151,8 +150,8 @@ public class PointCloud { float eta = PI/2.0f; float dEta = 2.0f * PI / pointsInBand; for (int i = 0; i < pointsInBand; i++) { - float x = r * FloatMath.cos(eta); - float y = r * FloatMath.sin(eta); + float x = r * (float) Math.cos(eta); + float y = r * (float) Math.sin(eta); eta += dEta; mPointCloud.add(new Point(x, y, r)); } @@ -167,32 +166,24 @@ public class PointCloud { return mScale; } - private static float hypot(float x, float y) { - return FloatMath.sqrt(x*x + y*y); - } - - private static float max(float a, float b) { - return a > b ? a : b; - } - public int getAlphaForPoint(Point point) { // Contribution from positional glow - float glowDistance = hypot(glowManager.x - point.x, glowManager.y - point.y); + float glowDistance = (float) Math.hypot(glowManager.x - point.x, glowManager.y - point.y); float glowAlpha = 0.0f; if (glowDistance < glowManager.radius) { - float cosf = FloatMath.cos(PI * 0.25f * glowDistance / glowManager.radius); - glowAlpha = glowManager.alpha * max(0.0f, (float) Math.pow(cosf, 10.0f)); + float cosf = (float) Math.cos(PI * 0.25f * glowDistance / glowManager.radius); + glowAlpha = glowManager.alpha * Math.max(0.0f, (float) Math.pow(cosf, 10.0f)); } // Compute contribution from Wave - float radius = hypot(point.x, point.y); + float radius = (float) Math.hypot(point.x, point.y); float waveAlpha = 0.0f; if (radius < waveManager.radius * 2) { float distanceToWaveRing = (radius - waveManager.radius); - float cosf = FloatMath.cos(PI * 0.5f * distanceToWaveRing / waveManager.radius); - waveAlpha = waveManager.alpha * max(0.0f, (float) Math.pow(cosf, 6.0f)); + float cosf = (float) Math.cos(PI * 0.5f * distanceToWaveRing / waveManager.radius); + waveAlpha = waveManager.alpha * Math.max(0.0f, (float) Math.pow(cosf, 6.0f)); } - return (int) (max(glowAlpha, waveAlpha) * 255); + return (int) (Math.max(glowAlpha, waveAlpha) * 255); } private float interp(float min, float max, float f) { |