Merge "Marquee text RTL improvements"
diff --git a/cmds/app_process/Android.mk b/cmds/app_process/Android.mk
index cb7e1a0..7c25354 100644
--- a/cmds/app_process/Android.mk
+++ b/cmds/app_process/Android.mk
@@ -14,30 +14,11 @@
 	libandroid_runtime
 
 LOCAL_MODULE:= app_process
-LOCAL_32_BIT_ONLY := true
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := app_process
+LOCAL_MODULE_STEM_64 := app_process64
 include $(BUILD_EXECUTABLE)
 
-ifeq ($(TARGET_IS_64_BIT),true)
-
-# 64-bit app_process64
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	app_main.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-	libutils \
-	liblog \
-	libbinder \
-	libandroid_runtime
-
-LOCAL_MODULE:= app_process64
-LOCAL_NO_2ND_ARCH := true
-include $(BUILD_EXECUTABLE)
-
-endif # TARGET_IS_64_BIT
-
 # Build a variant of app_process binary linked with ASan runtime.
 # ARM-only at the moment.
 ifeq ($(TARGET_ARCH),arm)
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 8d2b739..bdbb08c 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -30,8 +30,9 @@
 class AppRuntime : public AndroidRuntime
 {
 public:
-    AppRuntime()
-        : mParentDir(NULL)
+    AppRuntime(char* argBlockStart, const size_t argBlockLength)
+        : AndroidRuntime(argBlockStart, argBlockLength)
+        , mParentDir(NULL)
         , mClassName(NULL)
         , mClass(NULL)
         , mArgC(0)
@@ -125,29 +126,30 @@
 
 using namespace android;
 
-/*
- * sets argv0 to as much of newArgv0 as will fit
- */
-static void setArgv0(const char *argv0, const char *newArgv0)
-{
-    strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0));
+static size_t computeArgBlockSize(int argc, char* const argv[]) {
+    // TODO: This assumes that all arguments are allocated in
+    // contiguous memory. There isn't any documented guarantee
+    // that this is the case, but this is how the kernel does it
+    // (see fs/exec.c).
+    //
+    // Also note that this is a constant for "normal" android apps.
+    // Since they're forked from zygote, the size of their command line
+    // is the size of the zygote command line.
+    //
+    // We change the process name of the process by over-writing
+    // the start of the argument block (argv[0]) with the new name of
+    // the process, so we'd mysteriously start getting truncated process
+    // names if the zygote command line decreases in size.
+    uintptr_t start = reinterpret_cast<uintptr_t>(argv[0]);
+    uintptr_t end = reinterpret_cast<uintptr_t>(argv[argc - 1]);
+    end += strlen(argv[argc - 1]);
+
+    return (end - start);
 }
 
 int main(int argc, char* const argv[])
 {
-    // These are global variables in ProcessState.cpp
-    mArgC = argc;
-    mArgV = argv;
-
-    mArgLen = 0;
-    for (int i=0; i<argc; i++) {
-        mArgLen += strlen(argv[i]) + 1;
-    }
-    mArgLen--;
-
-    AppRuntime runtime;
-    const char* argv0 = argv[0];
-
+    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
     // Process command line arguments
     // ignore argv[0]
     argc--;
@@ -184,7 +186,7 @@
     }
 
     if (niceName && *niceName) {
-        setArgv0(argv0, niceName);
+        runtime.setArgv0(niceName);
         set_process_name(niceName);
     }
 
diff --git a/core/java/android/net/http/CertificateChainValidator.java b/core/java/android/net/http/CertificateChainValidator.java
index a28b5a7..d06355d 100644
--- a/core/java/android/net/http/CertificateChainValidator.java
+++ b/core/java/android/net/http/CertificateChainValidator.java
@@ -22,6 +22,8 @@
 import java.io.IOException;
 import java.lang.reflect.Method;
 import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
@@ -74,13 +76,16 @@
     private CertificateChainValidator() {
         try {
             TrustManagerFactory tmf = TrustManagerFactory.getInstance("X.509");
+            tmf.init((KeyStore) null);
             for (TrustManager tm : tmf.getTrustManagers()) {
                 if (tm instanceof X509ExtendedTrustManager) {
                     mTrustManager = (X509ExtendedTrustManager) tm;
                 }
             }
         } catch (NoSuchAlgorithmException e) {
-            throw new RuntimeException("X.509 TrustManager factory must be available", e);
+            throw new RuntimeException("X.509 TrustManagerFactory must be available", e);
+        } catch (KeyStoreException e) {
+            throw new RuntimeException("X.509 TrustManagerFactory cannot be initialized", e);
         }
 
         if (mTrustManager == null) {
@@ -166,9 +171,13 @@
         TrustManagerFactory tmf;
         try {
             tmf = TrustManagerFactory.getInstance("X.509");
+            tmf.init((KeyStore) null);
         } catch (NoSuchAlgorithmException e) {
             Slog.w(TAG, "Couldn't find default X.509 TrustManagerFactory");
             return;
+        } catch (KeyStoreException e) {
+            Slog.w(TAG, "Couldn't initialize default X.509 TrustManagerFactory", e);
+            return;
         }
 
         TrustManager[] tms = tmf.getTrustManagers();
diff --git a/core/java/android/net/http/X509TrustManagerExtensions.java b/core/java/android/net/http/X509TrustManagerExtensions.java
index 666832a..d730a7b 100644
--- a/core/java/android/net/http/X509TrustManagerExtensions.java
+++ b/core/java/android/net/http/X509TrustManagerExtensions.java
@@ -56,7 +56,8 @@
         if (tm instanceof TrustManagerImpl) {
             mDelegate = (TrustManagerImpl) tm;
         } else {
-            throw new IllegalArgumentException("tm is not a supported type of X509TrustManager");
+            throw new IllegalArgumentException("tm is an instance of " + tm.getClass().getName() +
+                    " which is not a supported type of X509TrustManager");
         }
     }
 
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 631edd6..4cf8767 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -16,10 +16,11 @@
 
 package android.os;
 
-import android.net.LocalSocketAddress;
 import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
 import android.util.Log;
-import dalvik.system.Zygote;
+
+import com.android.internal.os.Zygote;
 
 import java.io.BufferedWriter;
 import java.io.DataInputStream;
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index aa43bad..cd905fa 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -591,6 +591,7 @@
             Object[] args = mConstructorArgs;
             args[1] = attrs;
 
+            constructor.setAccessible(true);
             final View view = constructor.newInstance(args);
             if (view instanceof ViewStub) {
                 // always use ourselves when inflating ViewStub later
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index bc0d7e3..3fd2aa9 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -660,7 +660,7 @@
         mHandler.sendMessageAtFrontOfQueue(mHandler.obtainMessage(MSG_FLUSH_LAYER_UPDATES));
     }
 
-    public boolean attachFunctor(int functor) {
+    public boolean attachFunctor(long functor) {
         //noinspection SimplifiableIfStatement
         if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
             return mAttachInfo.mHardwareRenderer.attachFunctor(mAttachInfo, functor);
@@ -668,7 +668,7 @@
         return false;
     }
 
-    public void detachFunctor(int functor) {
+    public void detachFunctor(long functor) {
         if (mAttachInfo.mHardwareRenderer != null) {
             mAttachInfo.mHardwareRenderer.detachFunctor(functor);
         }
diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java
index c6b3e7c..3301cbe 100644
--- a/core/java/com/android/internal/os/WrapperInit.java
+++ b/core/java/com/android/internal/os/WrapperInit.java
@@ -25,9 +25,6 @@
 import java.io.IOException;
 
 import libcore.io.IoUtils;
-import libcore.io.Libcore;
-
-import dalvik.system.Zygote;
 
 /**
  * Startup class for the wrapper process.
@@ -95,7 +92,7 @@
      * @param niceName The nice name for the application, or null if none.
      * @param targetSdkVersion The target SDK version for the app.
      * @param pipeFd The pipe to which the application's pid should be written, or null if none.
-     * @param args Arguments for {@link RuntimeInit.main}.
+     * @param args Arguments for {@link RuntimeInit#main}.
      */
     public static void execApplication(String invokeWith, String niceName,
             int targetSdkVersion, FileDescriptor pipeFd, String[] args) {
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
new file mode 100644
index 0000000..c5fa0a1
--- /dev/null
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2014 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 dalvik.system.ZygoteHooks;
+import libcore.io.ErrnoException;
+import libcore.io.Libcore;
+
+/** @hide */
+public final class Zygote {
+    /*
+    * Bit values for "debugFlags" argument.  The definitions are duplicated
+    * in the native code.
+    */
+
+    /** enable debugging over JDWP */
+    public static final int DEBUG_ENABLE_DEBUGGER   = 1;
+    /** enable JNI checks */
+    public static final int DEBUG_ENABLE_CHECKJNI   = 1 << 1;
+    /** enable Java programming language "assert" statements */
+    public static final int DEBUG_ENABLE_ASSERT     = 1 << 2;
+    /** disable the JIT compiler */
+    public static final int DEBUG_ENABLE_SAFEMODE   = 1 << 3;
+    /** Enable logging of third-party JNI activity. */
+    public static final int DEBUG_ENABLE_JNI_LOGGING = 1 << 4;
+
+    /** No external storage should be mounted. */
+    public static final int MOUNT_EXTERNAL_NONE = 0;
+    /** Single-user external storage should be mounted. */
+    public static final int MOUNT_EXTERNAL_SINGLEUSER = 1;
+    /** Multi-user external storage should be mounted. */
+    public static final int MOUNT_EXTERNAL_MULTIUSER = 2;
+    /** All multi-user external storage should be mounted. */
+    public static final int MOUNT_EXTERNAL_MULTIUSER_ALL = 3;
+
+    private static final ZygoteHooks VM_HOOKS = new ZygoteHooks();
+
+    private Zygote() {}
+
+    /**
+     * Forks a new VM instance.  The current VM must have been started
+     * with the -Xzygote flag. <b>NOTE: new instance keeps all
+     * root capabilities. The new process is expected to call capset()</b>.
+     *
+     * @param uid the UNIX uid that the new process should setuid() to after
+     * fork()ing and and before spawning any threads.
+     * @param gid the UNIX gid that the new process should setgid() to after
+     * fork()ing and and before spawning any threads.
+     * @param gids null-ok; a list of UNIX gids that the new process should
+     * setgroups() to after fork and before spawning any threads.
+     * @param debugFlags bit flags that enable debugging features.
+     * @param rlimits null-ok an array of rlimit tuples, with the second
+     * dimension having a length of 3 and representing
+     * (resource, rlim_cur, rlim_max). These are set via the posix
+     * setrlimit(2) call.
+     * @param seInfo null-ok a string specifying SELinux information for
+     * the new process.
+     * @param niceName null-ok a string specifying the process name.
+     * @param fdsToClose an array of ints, holding one or more POSIX
+     * file descriptor numbers that are to be closed by the child
+     * (and replaced by /dev/null) after forking.  An integer value
+     * of -1 in any entry in the array means "ignore this one".
+     *
+     * @return 0 if this is the child, pid of the child
+     * if this is the parent, or -1 on error.
+     */
+    public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
+          int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose) {
+        VM_HOOKS.preFork();
+        int pid = nativeForkAndSpecialize(
+                  uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose);
+        VM_HOOKS.postForkCommon();
+        return pid;
+    }
+
+    native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int debugFlags,
+          int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose);
+
+    /**
+     * 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
+     * zygote to exit.
+     *
+     * @param uid the UNIX uid that the new process should setuid() to after
+     * fork()ing and and before spawning any threads.
+     * @param gid the UNIX gid that the new process should setgid() to after
+     * fork()ing and and before spawning any threads.
+     * @param gids null-ok; a list of UNIX gids that the new process should
+     * setgroups() to after fork and before spawning any threads.
+     * @param debugFlags bit flags that enable debugging features.
+     * @param rlimits null-ok an array of rlimit tuples, with the second
+     * dimension having a length of 3 and representing
+     * (resource, rlim_cur, rlim_max). These are set via the posix
+     * setrlimit(2) call.
+     * @param permittedCapabilities argument for setcap()
+     * @param effectiveCapabilities argument for setcap()
+     *
+     * @return 0 if this is the child, pid of the child
+     * if this is the parent, or -1 on error.
+     */
+    public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
+            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
+        VM_HOOKS.preFork();
+        int pid = nativeForkSystemServer(
+                uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
+        VM_HOOKS.postForkCommon();
+        return pid;
+    }
+
+    native private static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags,
+            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
+
+    private static void callPostForkChildHooks(int debugFlags) {
+        VM_HOOKS.postForkChild(debugFlags);
+    }
+
+
+    /**
+     * Executes "/system/bin/sh -c &lt;command&gt;" using the exec() system call.
+     * This method throws a runtime exception if exec() failed, otherwise, this
+     * method never returns.
+     *
+     * @param command The shell command to execute.
+     */
+    public static void execShell(String command) {
+        String[] args = { "/system/bin/sh", "-c", command };
+        try {
+            Libcore.os.execv(args[0], args);
+        } catch (ErrnoException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Appends quotes shell arguments to the specified string builder.
+     * The arguments are quoted using single-quotes, escaped if necessary,
+     * prefixed with a space, and appended to the command.
+     *
+     * @param command A string builder for the shell command being constructed.
+     * @param args An array of argument strings to be quoted and appended to the command.
+     * @see #execShell(String)
+     */
+    public static void appendQuotedShellArgs(StringBuilder command, String[] args) {
+        for (String arg : args) {
+            command.append(" '").append(arg.replace("'", "'\\''")).append("'");
+        }
+    }
+}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index f9a1f89..aad534c 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -24,7 +24,6 @@
 import android.util.Log;
 
 import dalvik.system.PathClassLoader;
-import dalvik.system.Zygote;
 
 import java.io.BufferedReader;
 import java.io.DataInputStream;
@@ -807,7 +806,7 @@
     /**
      * Applies invoke-with system properties to the zygote arguments.
      *
-     * @param parsedArgs non-null; zygote args
+     * @param args non-null; zygote args
      */
     public static void applyInvokeWithSystemProperty(Arguments args) {
         if (args.invokeWith == null && args.niceName != null) {
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index cc24ff7..5be29b4 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -32,7 +32,6 @@
 import android.util.Log;
 
 import dalvik.system.VMRuntime;
-import dalvik.system.Zygote;
 
 import libcore.io.IoUtils;
 import libcore.io.Libcore;
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index ac70738..fda4114 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -149,7 +149,8 @@
 	android_content_res_ObbScanner.cpp \
 	android_content_res_Configuration.cpp \
 	android_animation_PropertyValuesHolder.cpp \
-	com_android_internal_net_NetworkStatsFactory.cpp
+	com_android_internal_net_NetworkStatsFactory.cpp \
+	com_android_internal_os_Zygote.cpp
 
 LOCAL_C_INCLUDES += \
 	$(JNI_H_INCLUDE) \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 649968e..cce4e0d 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -177,6 +177,7 @@
 extern int register_android_animation_PropertyValuesHolder(JNIEnv *env);
 extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env);
 extern int register_com_android_internal_net_NetworkStatsFactory(JNIEnv *env);
+extern int register_com_android_internal_os_Zygote(JNIEnv *env);
 
 static AndroidRuntime* gCurRuntime = NULL;
 
@@ -227,9 +228,10 @@
 
 /*static*/ JavaVM* AndroidRuntime::mJavaVM = NULL;
 
-
-AndroidRuntime::AndroidRuntime() :
-        mExitWithoutCleanup(false)
+AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) :
+        mExitWithoutCleanup(false),
+        mArgBlockStart(argBlockStart),
+        mArgBlockLength(argBlockLength)
 {
     SkGraphics::Init();
     // this sets our preference for 16bit images during decode
@@ -264,6 +266,10 @@
     return jniRegisterNativeMethods(env, className, gMethods, numMethods);
 }
 
+void AndroidRuntime::setArgv0(const char* argv0) {
+    strlcpy(mArgBlockStart, argv0, mArgBlockLength);
+}
+
 status_t AndroidRuntime::callMain(const char* className,
     jclass clazz, int argc, const char* const argv[])
 {
@@ -1241,6 +1247,7 @@
     REG_JNI(register_android_net_wifi_WifiNative),
     REG_JNI(register_android_os_MemoryFile),
     REG_JNI(register_com_android_internal_os_ZygoteInit),
+    REG_JNI(register_com_android_internal_os_Zygote),
     REG_JNI(register_android_hardware_Camera),
     REG_JNI(register_android_hardware_camera2_CameraMetadata),
     REG_JNI(register_android_hardware_SensorManager),
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 92d253f..e2c78b1 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -69,7 +69,7 @@
     size_t totalSizeToDelete = text.getSize() + desc->getSize();
     mSize -= totalSizeToDelete;
     if (mDebugEnabled) {
-        ALOGD("Cache value %p deleted, size = %d", desc.get(), totalSizeToDelete);
+        ALOGD("Cache value %p deleted, size = %zu", desc.get(), totalSizeToDelete);
     }
 }
 
@@ -129,7 +129,7 @@
                     bool removedOne = mCache.removeOldest();
                     LOG_ALWAYS_FATAL_IF(!removedOne, "The cache is non-empty but we "
                             "failed to remove the oldest entry.  "
-                            "mSize = %u, size = %u, mMaxSize = %u, mCache.size() = %u",
+                            "mSize = %u, size = %zu, mMaxSize = %u, mCache.size() = %zu",
                             mSize, size, mMaxSize, mCache.size());
                 }
             }
@@ -148,7 +148,7 @@
                 nsecs_t totalTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;
                 ALOGD("CACHE MISS: Added entry %p "
                         "with start = %d, count = %d, contextCount = %d, "
-                        "entry size %d bytes, remaining space %d bytes"
+                        "entry size %zu bytes, remaining space %d bytes"
                         " - Compute time %0.6f ms - Put time %0.6f ms - Text = '%s'",
                         value.get(), start, count, contextCount, size, mMaxSize - mSize,
                         value->getElapsedTime() * 0.000001f,
@@ -159,7 +159,7 @@
             if (mDebugEnabled) {
                 ALOGD("CACHE MISS: Calculated but not storing entry because it is too big "
                         "with start = %d, count = %d, contextCount = %d, "
-                        "entry size %d bytes, remaining space %d bytes"
+                        "entry size %zu bytes, remaining space %d bytes"
                         " - Compute time %0.6f ms - Text = '%s'",
                         start, count, contextCount, size, mMaxSize - mSize,
                         value->getElapsedTime() * 0.000001f,
@@ -204,7 +204,7 @@
     ALOGD("------------------------------------------------");
     ALOGD("pid       : %d", getpid());
     ALOGD("running   : %.0f seconds", timeRunningInSec);
-    ALOGD("entries   : %d", cacheSize);
+    ALOGD("entries   : %zu", cacheSize);
     ALOGD("max size  : %d bytes", mMaxSize);
     ALOGD("used      : %d bytes according to mSize", mSize);
     ALOGD("remaining : %d bytes or %2.2f percent", mMaxSize - mSize, remainingPercent);
diff --git a/core/jni/android_net_LocalSocketImpl.cpp b/core/jni/android_net_LocalSocketImpl.cpp
index 9f79f74..98f4bed 100644
--- a/core/jni/android_net_LocalSocketImpl.cpp
+++ b/core/jni/android_net_LocalSocketImpl.cpp
@@ -111,7 +111,7 @@
 
 /* private native void listen_native(int fd, int backlog) throws IOException; */
 static void
-socket_listen (JNIEnv *env, jobject object, jobject fileDescriptor, int backlog)
+socket_listen (JNIEnv *env, jobject object, jobject fileDescriptor, jint backlog)
 {
     int ret;
     int fd;
@@ -231,7 +231,7 @@
 }
 
 static jint
-socket_getOption(JNIEnv *env, jobject object, jobject fileDescriptor, int optID)
+socket_getOption(JNIEnv *env, jobject object, jobject fileDescriptor, jint optID)
 {
     int ret, value;
     int opt, level;
@@ -279,7 +279,7 @@
 }
 
 static void socket_setOption(
-        JNIEnv *env, jobject object, jobject fileDescriptor, int optID,
+        JNIEnv *env, jobject object, jobject fileDescriptor, jint optID,
         jint boolValue, jint intValue) {
     int ret;
     int optname;
diff --git a/core/jni/android_nio_utils.cpp b/core/jni/android_nio_utils.cpp
index 7cbbe12..59d6e41 100644
--- a/core/jni/android_nio_utils.cpp
+++ b/core/jni/android_nio_utils.cpp
@@ -37,7 +37,7 @@
                                          gNioJNI.getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void *>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(gNioJNI.nioAccessClass,
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index a041693..d4873d6 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -800,7 +800,7 @@
     fprintf(fp, "Total memory: %zu\n", totalMemory);
     fprintf(fp, "Allocation records: %zd\n", recordCount);
     if (backtraceSize != BACKTRACE_SIZE) {
-        fprintf(fp, "WARNING: mismatched backtrace sizes (%d vs. %d)\n",
+        fprintf(fp, "WARNING: mismatched backtrace sizes (%zu vs. %d)\n",
             backtraceSize, BACKTRACE_SIZE);
     }
     fprintf(fp, "\n");
@@ -823,7 +823,11 @@
             if (backtrace[bt] == 0) {
                 break;
             } else {
+#ifdef __LP64__
+                fprintf(fp, " %016x", backtrace[bt]);
+#else
                 fprintf(fp, " %08x", backtrace[bt]);
+#endif
             }
         }
         fprintf(fp, "\n");
diff --git a/core/jni/android_server_NetworkManagementSocketTagger.cpp b/core/jni/android_server_NetworkManagementSocketTagger.cpp
index 12beff7..7e12b1e 100644
--- a/core/jni/android_server_NetworkManagementSocketTagger.cpp
+++ b/core/jni/android_server_NetworkManagementSocketTagger.cpp
@@ -47,8 +47,8 @@
   return (jint)res;
 }
 
-static int QTagUid_untagSocketFd(JNIEnv* env, jclass,
-                                 jobject fileDescriptor) {
+static jint QTagUid_untagSocketFd(JNIEnv* env, jclass,
+                                  jobject fileDescriptor) {
   int userFd = jniGetFDFromFileDescriptor(env, fileDescriptor);
 
   if (env->ExceptionOccurred() != NULL) {
diff --git a/core/jni/android_text_AndroidBidi.cpp b/core/jni/android_text_AndroidBidi.cpp
index d50a69f..6f7ee49 100644
--- a/core/jni/android_text_AndroidBidi.cpp
+++ b/core/jni/android_text_AndroidBidi.cpp
@@ -26,7 +26,7 @@
 namespace android {
 
 static jint runBidi(JNIEnv* env, jobject obj, jint dir, jcharArray chsArray,
-                    jbyteArray infoArray, int n, jboolean haveInfo)
+                    jbyteArray infoArray, jint n, jboolean haveInfo)
 {
     // Parameters are checked on java side
     // Failures from GetXXXArrayElements indicate a serious out-of-memory condition
diff --git a/core/jni/android_text_AndroidCharacter.cpp b/core/jni/android_text_AndroidCharacter.cpp
index 8b85a7b7..94bd40f 100644
--- a/core/jni/android_text_AndroidCharacter.cpp
+++ b/core/jni/android_text_AndroidCharacter.cpp
@@ -51,7 +51,8 @@
 
 namespace android {
 
-static void getDirectionalities(JNIEnv* env, jobject obj, jcharArray srcArray, jbyteArray destArray, int count)
+static void getDirectionalities(JNIEnv* env, jobject obj, jcharArray srcArray,
+                                jbyteArray destArray, jint count)
 {
     ScopedCharArrayRO src(env, srcArray);
     if (src.get() == NULL) {
@@ -102,7 +103,7 @@
 }
 
 static void getEastAsianWidths(JNIEnv* env, jobject obj, jcharArray srcArray,
-                               int start, int count, jbyteArray destArray)
+                               jint start, jint count, jbyteArray destArray)
 {
     ScopedCharArrayRO src(env, srcArray);
     if (src.get() == NULL) {
@@ -144,20 +145,20 @@
     }
 }
 
-static jboolean mirror(JNIEnv* env, jobject obj, jcharArray charArray, int start, int count)
+static jboolean mirror(JNIEnv* env, jobject obj, jcharArray charArray, jint start, jint count)
 {
     ScopedCharArrayRW data(env, charArray);
     if (data.get() == NULL) {
-        return false;
+        return JNI_FALSE;
     }
 
     if (start < 0 || start > start + count
             || env->GetArrayLength(charArray) < start + count) {
         jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
-        return false;
+        return JNI_FALSE;
     }
 
-    bool ret = false;
+    jboolean ret = JNI_FALSE;
     for (int i = start; i < start + count; i++) {
         // XXX this thinks it knows that surrogates are never mirrored
 
@@ -166,7 +167,7 @@
 
         if (c1 != c2) {
             data[i] = c2;
-            ret = true;
+            ret = JNI_TRUE;
         }
     }
     return ret;
diff --git a/core/jni/android_text_format_Time.cpp b/core/jni/android_text_format_Time.cpp
index aa2c5f39..28a8a5d 100644
--- a/core/jni/android_text_format_Time.cpp
+++ b/core/jni/android_text_format_Time.cpp
@@ -117,7 +117,7 @@
     time2java(env, This, t);
     RELEASE_TIMEZONE(This, t)
 
-    return result;
+    return static_cast<jlong>(result);
 }
 
 static void android_text_format_Time_switchTimezone(JNIEnv* env, jobject This,
@@ -155,7 +155,7 @@
     RELEASE_TIMEZONE(aObject, a)
     RELEASE_TIMEZONE(bObject, b)
 
-    return result;
+    return static_cast<jint>(result);
 }
 
 static jstring android_text_format_Time_format2445(JNIEnv* env, jobject This)
@@ -346,7 +346,7 @@
 
     RELEASE_TIMEZONE(This, t)
 
-    return result;
+    return static_cast<jlong>(result);
 }
 
 static void android_text_format_Time_set(JNIEnv* env, jobject This, jlong millis)
@@ -400,10 +400,10 @@
     if (len < 8) {
         jniThrowException(env, "android/util/TimeFormatException",
                           "String too short -- expected at least 8 characters.");
-        return false;
+        return JNI_FALSE;
     }
 
-    jboolean inUtc = false;
+    jboolean inUtc = JNI_FALSE;
 
     ScopedStringChars s(env, strObj);
 
@@ -414,49 +414,49 @@
     n += get_char(env, s, 1, 100, &thrown);
     n += get_char(env, s, 2, 10, &thrown);
     n += get_char(env, s, 3, 1, &thrown);
-    if (thrown) return false;
+    if (thrown) return JNI_FALSE;
     env->SetIntField(This, g_yearField, n);
 
     // month
     n = get_char(env, s, 4, 10, &thrown);
     n += get_char(env, s, 5, 1, &thrown);
     n--;
-    if (thrown) return false;
+    if (thrown) return JNI_FALSE;
     env->SetIntField(This, g_monField, n);
 
     // day of month
     n = get_char(env, s, 6, 10, &thrown);
     n += get_char(env, s, 7, 1, &thrown);
-    if (thrown) return false;
+    if (thrown) return JNI_FALSE;
     env->SetIntField(This, g_mdayField, n);
 
     if (len > 8) {
         // T
-        if (!check_char(env, s, 8, 'T')) return false;
+        if (!check_char(env, s, 8, 'T')) return JNI_FALSE;
         env->SetBooleanField(This, g_allDayField, JNI_FALSE);
 
         // hour
         n = get_char(env, s, 9, 10, &thrown);
         n += get_char(env, s, 10, 1, &thrown);
-        if (thrown) return false;
+        if (thrown) return JNI_FALSE;
         env->SetIntField(This, g_hourField, n);
 
         // min
         n = get_char(env, s, 11, 10, &thrown);
         n += get_char(env, s, 12, 1, &thrown);
-        if (thrown) return false;
+        if (thrown) return JNI_FALSE;
         env->SetIntField(This, g_minField, n);
 
         // sec
         n = get_char(env, s, 13, 10, &thrown);
         n += get_char(env, s, 14, 1, &thrown);
-        if (thrown) return false;
+        if (thrown) return JNI_FALSE;
         env->SetIntField(This, g_secField, n);
 
         if (len > 15) {
             // Z
-            if (!check_char(env, s, 15, 'Z')) return false;
-            inUtc = true;
+            if (!check_char(env, s, 15, 'Z')) return JNI_FALSE;
+            inUtc = JNI_TRUE;
         }
     } else {
         env->SetBooleanField(This, g_allDayField, JNI_TRUE);
@@ -481,10 +481,10 @@
     if (len < 10) {
         jniThrowException(env, "android/util/TimeFormatException",
                           "String too short --- expected at least 10 characters.");
-        return false;
+        return JNI_FALSE;
     }
 
-    jboolean inUtc = false;
+    jboolean inUtc = JNI_FALSE;
 
     ScopedStringChars s(env, strObj);
 
@@ -495,57 +495,57 @@
     n += get_char(env, s, 1, 100, &thrown);
     n += get_char(env, s, 2, 10, &thrown);
     n += get_char(env, s, 3, 1, &thrown);
-    if (thrown) return false;
+    if (thrown) return JNI_FALSE;
     env->SetIntField(This, g_yearField, n);
     
     // -
-    if (!check_char(env, s, 4, '-')) return false;
+    if (!check_char(env, s, 4, '-')) return JNI_FALSE;
     
     // month
     n = get_char(env, s, 5, 10, &thrown);
     n += get_char(env, s, 6, 1, &thrown);
     --n;
-    if (thrown) return false;
+    if (thrown) return JNI_FALSE;
     env->SetIntField(This, g_monField, n);
 
     // -
-    if (!check_char(env, s, 7, '-')) return false;
+    if (!check_char(env, s, 7, '-')) return JNI_FALSE;
 
     // day
     n = get_char(env, s, 8, 10, &thrown);
     n += get_char(env, s, 9, 1, &thrown);
-    if (thrown) return false;
+    if (thrown) return JNI_FALSE;
     env->SetIntField(This, g_mdayField, n);
 
     if (len >= 19) {
         // T
-        if (!check_char(env, s, 10, 'T')) return false;
+        if (!check_char(env, s, 10, 'T')) return JNI_FALSE;
 
         env->SetBooleanField(This, g_allDayField, JNI_FALSE);
         // hour
         n = get_char(env, s, 11, 10, &thrown);
         n += get_char(env, s, 12, 1, &thrown);
-        if (thrown) return false;
+        if (thrown) return JNI_FALSE;
         int hour = n;
         // env->SetIntField(This, g_hourField, n);
 
         // :
-        if (!check_char(env, s, 13, ':')) return false;
+        if (!check_char(env, s, 13, ':')) return JNI_FALSE;
 
         // minute
         n = get_char(env, s, 14, 10, &thrown);
         n += get_char(env, s, 15, 1, &thrown);
-        if (thrown) return false;
+        if (thrown) return JNI_FALSE;
         int minute = n;
         // env->SetIntField(This, g_minField, n);
 
         // :
-        if (!check_char(env, s, 16, ':')) return false;
+        if (!check_char(env, s, 16, ':')) return JNI_FALSE;
 
         // second
         n = get_char(env, s, 17, 10, &thrown);
         n += get_char(env, s, 18, 1, &thrown);
-        if (thrown) return false;
+        if (thrown) return JNI_FALSE;
         env->SetIntField(This, g_secField, n);
 
         // skip the '.XYZ' -- we don't care about subsecond precision.
@@ -579,32 +579,32 @@
                 jniThrowExceptionFmt(env, "android/util/TimeFormatException",
                                      "Unexpected character 0x%02x at position %d.  Expected + or -",
                                      c, tz_index);
-                return false;
+                return JNI_FALSE;
             }
-            inUtc = true;
+            inUtc = JNI_TRUE;
 
             if (offset != 0) {
                 if (len < tz_index + 6) {
                     jniThrowExceptionFmt(env, "android/util/TimeFormatException",
                                          "Unexpected length; should be %d characters",
                                          tz_index + 6);
-                    return false;
+                    return JNI_FALSE;
                 }
 
                 // hour
                 n = get_char(env, s, tz_index + 1, 10, &thrown);
                 n += get_char(env, s, tz_index + 2, 1, &thrown);
-                if (thrown) return false;
+                if (thrown) return JNI_FALSE;
                 n *= offset;
                 hour += n;
 
                 // :
-                if (!check_char(env, s, tz_index + 3, ':')) return false;
+                if (!check_char(env, s, tz_index + 3, ':')) return JNI_FALSE;
             
                 // minute
                 n = get_char(env, s, tz_index + 4, 10, &thrown);
                 n += get_char(env, s, tz_index + 5, 1, &thrown);
-                if (thrown) return false;
+                if (thrown) return JNI_FALSE;
                 n *= offset;
                 minute += n;
             }
diff --git a/core/jni/android_util_Log.cpp b/core/jni/android_util_Log.cpp
index 536a582..93dcbef 100644
--- a/core/jni/android_util_Log.cpp
+++ b/core/jni/android_util_Log.cpp
@@ -85,7 +85,7 @@
     jboolean result = false;
     if ((strlen(chars)+sizeof(LOG_NAMESPACE)) > PROPERTY_KEY_MAX) {
         char buf2[200];
-        snprintf(buf2, sizeof(buf2), "Log tag \"%s\" exceeds limit of %d characters\n",
+        snprintf(buf2, sizeof(buf2), "Log tag \"%s\" exceeds limit of %zu characters\n",
                 chars, PROPERTY_KEY_MAX - sizeof(LOG_NAMESPACE));
 
         jniThrowException(env, "java/lang/IllegalArgumentException", buf2);
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 601975a..9f8eb34 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -19,8 +19,8 @@
 
 #include <utils/Log.h>
 #include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
+#include <cutils/process_name.h>
 #include <cutils/sched_policy.h>
 #include <utils/String8.h>
 #include <utils/Vector.h>
@@ -402,7 +402,9 @@
     }
 
     if (name8.size() > 0) {
-        ProcessState::self()->setArgV0(name8.string());
+        const char* procName = name8.string();
+        set_process_name(procName);
+        AndroidRuntime::getRuntime()->setArgv0(procName);
     }
 }
 
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
new file mode 100644
index 0000000..a61fa87
--- /dev/null
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -0,0 +1,608 @@
+/*
+ * 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.
+ */
+
+#include "android_runtime/AndroidRuntime.h"
+
+// sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc
+#include <sys/mount.h>
+#include <linux/fs.h>
+
+#include <grp.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "cutils/fs.h"
+#include "cutils/multiuser.h"
+#include "cutils/sched_policy.h"
+#include "utils/String8.h"
+#include "JNIHelp.h"
+#include "ScopedLocalRef.h"
+#include "ScopedPrimitiveArray.h"
+#include "ScopedUtfChars.h"
+
+#if defined(HAVE_PRCTL)
+#include <sys/prctl.h>
+#endif
+
+#include <selinux/android.h>
+
+#if defined(__linux__)
+#include <sys/personality.h>
+#include <sys/utsname.h>
+#if defined(HAVE_ANDROID_OS)
+#include <sys/capability.h>
+#endif
+#endif
+
+namespace {
+
+using android::String8;
+
+static pid_t gSystemServerPid = 0;
+
+static const char kZygoteClassName[] = "com/android/internal/os/Zygote";
+static jclass gZygoteClass;
+static jmethodID gCallPostForkChildHooks;
+
+// Must match values in com.android.internal.os.Zygote.
+enum MountExternalKind {
+  MOUNT_EXTERNAL_NONE = 0,
+  MOUNT_EXTERNAL_SINGLEUSER = 1,
+  MOUNT_EXTERNAL_MULTIUSER = 2,
+  MOUNT_EXTERNAL_MULTIUSER_ALL = 3,
+};
+
+static void RuntimeAbort(JNIEnv* env) {
+  env->FatalError("RuntimeAbort");
+}
+
+// This signal handler is for zygote mode, since the zygote must reap its children
+static void SigChldHandler(int /*signal_number*/) {
+  pid_t pid;
+  int status;
+
+  while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
+     // Log process-death status that we care about.  In general it is
+     // not safe to call LOG(...) from a signal handler because of
+     // possible reentrancy.  However, we know a priori that the
+     // current implementation of LOG() is safe to call from a SIGCHLD
+     // handler in the zygote process.  If the LOG() implementation
+     // changes its locking strategy or its use of syscalls within the
+     // lazy-init critical section, its use here may become unsafe.
+    if (WIFEXITED(status)) {
+      if (WEXITSTATUS(status)) {
+        ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
+      } else if (false) {
+        ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
+      }
+    } else if (WIFSIGNALED(status)) {
+      if (WTERMSIG(status) != SIGKILL) {
+        ALOGI("Process %d exited cleanly (%d)", pid, WTERMSIG(status));
+      } else if (false) {
+        ALOGI("Process %d exited cleanly (%d)", pid, WTERMSIG(status));
+      }
+#ifdef WCOREDUMP
+      if (WCOREDUMP(status)) {
+        ALOGI("Process %d dumped core.", pid);
+      }
+#endif /* ifdef WCOREDUMP */
+    }
+
+    // If the just-crashed process is the system_server, bring down zygote
+    // so that it is restarted by init and system server will be restarted
+    // from there.
+    if (pid == gSystemServerPid) {
+      ALOGE("Exit zygote because system server (%d) has terminated");
+      kill(getpid(), SIGKILL);
+    }
+  }
+
+  if (pid < 0) {
+    ALOGW("Zygote SIGCHLD error in waitpid: %d", errno);
+  }
+}
+
+// Configures the SIGCHLD handler for the zygote process. This is configured
+// very late, because earlier in the runtime we may fork() and exec()
+// other processes, and we want to waitpid() for those rather than
+// have them be harvested immediately.
+//
+// This ends up being called repeatedly before each fork(), but there's
+// no real harm in that.
+static void SetSigChldHandler() {
+  struct sigaction sa;
+  memset(&sa, 0, sizeof(sa));
+  sa.sa_handler = SigChldHandler;
+
+  int err = sigaction(SIGCHLD, &sa, NULL);
+  if (err < 0) {
+    ALOGW("Error setting SIGCHLD handler: %d", errno);
+  }
+}
+
+// Sets the SIGCHLD handler back to default behavior in zygote children.
+static void UnsetSigChldHandler() {
+  struct sigaction sa;
+  memset(&sa, 0, sizeof(sa));
+  sa.sa_handler = SIG_DFL;
+
+  int err = sigaction(SIGCHLD, &sa, NULL);
+  if (err < 0) {
+    ALOGW("Error unsetting SIGCHLD handler: %d", errno);
+  }
+}
+
+// Calls POSIX setgroups() using the int[] object as an argument.
+// A NULL argument is tolerated.
+static void SetGids(JNIEnv* env, jintArray javaGids) {
+  if (javaGids == NULL) {
+    return;
+  }
+
+  ScopedIntArrayRO gids(env, javaGids);
+  if (gids.get() == NULL) {
+      RuntimeAbort(env);
+  }
+  int rc = setgroups(gids.size(), reinterpret_cast<const gid_t*>(&gids[0]));
+  if (rc == -1) {
+    ALOGE("setgroups failed");
+    RuntimeAbort(env);
+  }
+}
+
+// Sets the resource limits via setrlimit(2) for the values in the
+// two-dimensional array of integers that's passed in. The second dimension
+// contains a tuple of length 3: (resource, rlim_cur, rlim_max). NULL is
+// treated as an empty array.
+static void SetRLimits(JNIEnv* env, jobjectArray javaRlimits) {
+  if (javaRlimits == NULL) {
+    return;
+  }
+
+  rlimit rlim;
+  memset(&rlim, 0, sizeof(rlim));
+
+  for (int i = 0; i < env->GetArrayLength(javaRlimits); ++i) {
+    ScopedLocalRef<jobject> javaRlimitObject(env, env->GetObjectArrayElement(javaRlimits, i));
+    ScopedIntArrayRO javaRlimit(env, reinterpret_cast<jintArray>(javaRlimitObject.get()));
+    if (javaRlimit.size() != 3) {
+      ALOGE("rlimits array must have a second dimension of size 3");
+      RuntimeAbort(env);
+    }
+
+    rlim.rlim_cur = javaRlimit[1];
+    rlim.rlim_max = javaRlimit[2];
+
+    int rc = setrlimit(javaRlimit[0], &rlim);
+    if (rc == -1) {
+      ALOGE("setrlimit(%d, {%d, %d}) failed", javaRlimit[0], rlim.rlim_cur, rlim.rlim_max);
+      RuntimeAbort(env);
+    }
+  }
+}
+
+#if defined(HAVE_ANDROID_OS)
+
+// The debug malloc library needs to know whether it's the zygote or a child.
+extern "C" int gMallocLeakZygoteChild;
+
+static void EnableKeepCapabilities(JNIEnv* env) {
+  int rc = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+  if (rc == -1) {
+    ALOGE("prctl(PR_SET_KEEPCAPS) failed");
+    RuntimeAbort(env);
+  }
+}
+
+static void DropCapabilitiesBoundingSet(JNIEnv* env) {
+  for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
+    int rc = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
+    if (rc == -1) {
+      if (errno == EINVAL) {
+        ALOGE("prctl(PR_CAPBSET_DROP) failed with EINVAL. Please verify "
+              "your kernel is compiled with file capabilities support");
+      } else {
+        ALOGE("prctl(PR_CAPBSET_DROP) failed");
+        RuntimeAbort(env);
+      }
+    }
+  }
+}
+
+static void SetCapabilities(JNIEnv* env, int64_t permitted, int64_t effective) {
+  __user_cap_header_struct capheader;
+  memset(&capheader, 0, sizeof(capheader));
+  capheader.version = _LINUX_CAPABILITY_VERSION_3;
+  capheader.pid = 0;
+
+  __user_cap_data_struct capdata[2];
+  memset(&capdata, 0, sizeof(capdata));
+  capdata[0].effective = effective;
+  capdata[1].effective = effective >> 32;
+  capdata[0].permitted = permitted;
+  capdata[1].permitted = permitted >> 32;
+
+  if (capset(&capheader, &capdata[0]) == -1) {
+    ALOGE("capset(%lld, %lld) failed", permitted, effective);
+    RuntimeAbort(env);
+  }
+}
+
+static void SetSchedulerPolicy(JNIEnv* env) {
+  errno = -set_sched_policy(0, SP_DEFAULT);
+  if (errno != 0) {
+    ALOGE("set_sched_policy(0, SP_DEFAULT) failed");
+    RuntimeAbort(env);
+  }
+}
+
+#else
+
+static int gMallocLeakZygoteChild = 0;
+
+static void EnableKeepCapabilities(JNIEnv*) {}
+static void DropCapabilitiesBoundingSet(JNIEnv*) {}
+static void SetCapabilities(JNIEnv*, int64_t, int64_t) {}
+static void SetSchedulerPolicy(JNIEnv*) {}
+
+#endif
+
+// Create a private mount namespace and bind mount appropriate emulated
+// storage for the given user.
+static bool MountEmulatedStorage(uid_t uid, jint mount_mode) {
+  if (mount_mode == MOUNT_EXTERNAL_NONE) {
+    return true;
+  }
+
+  // See storage config details at http://source.android.com/tech/storage/
+  userid_t user_id = multiuser_get_user_id(uid);
+
+  // Create a second private mount namespace for our process
+  if (unshare(CLONE_NEWNS) == -1) {
+      ALOGW("Failed to unshare(): %d", errno);
+      return false;
+  }
+
+  // Create bind mounts to expose external storage
+  if (mount_mode == MOUNT_EXTERNAL_MULTIUSER || mount_mode == MOUNT_EXTERNAL_MULTIUSER_ALL) {
+    // These paths must already be created by init.rc
+    const char* source = getenv("EMULATED_STORAGE_SOURCE");
+    const char* target = getenv("EMULATED_STORAGE_TARGET");
+    const char* legacy = getenv("EXTERNAL_STORAGE");
+    if (source == NULL || target == NULL || legacy == NULL) {
+      ALOGW("Storage environment undefined; unable to provide external storage");
+      return false;
+    }
+
+    // Prepare source paths
+
+    // /mnt/shell/emulated/0
+    const String8 source_user(String8::format("%s/%d", source, user_id));
+    // /storage/emulated/0
+    const String8 target_user(String8::format("%s/%d", target, user_id));
+
+    if (fs_prepare_dir(source_user.string(), 0000, 0, 0) == -1
+        || fs_prepare_dir(target_user.string(), 0000, 0, 0) == -1) {
+      return false;
+    }
+
+    if (mount_mode == MOUNT_EXTERNAL_MULTIUSER_ALL) {
+      // Mount entire external storage tree for all users
+      if (TEMP_FAILURE_RETRY(mount(source, target, NULL, MS_BIND, NULL)) == -1) {
+        ALOGW("Failed to mount %s to %s :%d", source, target, errno);
+        return false;
+      }
+    } else {
+      // Only mount user-specific external storage
+      if (TEMP_FAILURE_RETRY(
+              mount(source_user.string(), target_user.string(), NULL, MS_BIND, NULL)) == -1) {
+        ALOGW("Failed to mount %s to %s: %d", source_user.string(), target_user.string(), errno);
+        return false;
+      }
+    }
+
+    if (fs_prepare_dir(legacy, 0000, 0, 0) == -1) {
+        return false;
+    }
+
+    // Finally, mount user-specific path into place for legacy users
+    if (TEMP_FAILURE_RETRY(
+            mount(target_user.string(), legacy, NULL, MS_BIND | MS_REC, NULL)) == -1) {
+      ALOGW("Failed to mount %s to %s: %d", target_user.string(), legacy, errno);
+      return false;
+    }
+  } else {
+    ALOGW("Mount mode %d unsupported", mount_mode);
+    return false;
+  }
+
+  return true;
+}
+
+#if defined(__linux__)
+static bool NeedsNoRandomizeWorkaround() {
+#if !defined(__arm__)
+    return false;
+#else
+    int major;
+    int minor;
+    struct utsname uts;
+    if (uname(&uts) == -1) {
+        return false;
+    }
+
+    if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
+        return false;
+    }
+
+    // Kernels before 3.4.* need the workaround.
+    return (major < 3) || ((major == 3) && (minor < 4));
+#endif
+}
+#endif
+
+// Utility to close down the Zygote socket file descriptors while
+// the child is still running as root with Zygote's privileges.  Each
+// descriptor (if any) is closed via dup2(), replacing it with a valid
+// (open) descriptor to /dev/null.
+
+static void DetachDescriptors(JNIEnv* env, jintArray fdsToClose) {
+  if (!fdsToClose) {
+    return;
+  }
+  jsize count = env->GetArrayLength(fdsToClose);
+  jint *ar = env->GetIntArrayElements(fdsToClose, 0);
+  if (!ar) {
+      ALOGE("Bad fd array");
+      RuntimeAbort(env);
+  }
+  jsize i;
+  int devnull;
+  for (i = 0; i < count; i++) {
+    devnull = open("/dev/null", O_RDWR);
+    if (devnull < 0) {
+      ALOGE("Failed to open /dev/null");
+      RuntimeAbort(env);
+      continue;
+    }
+    ALOGV("Switching descriptor %d to /dev/null: %d", ar[i], errno);
+    if (dup2(devnull, ar[i]) < 0) {
+      ALOGE("Failed dup2() on descriptor %d", ar[i]);
+      RuntimeAbort(env);
+    }
+    close(devnull);
+  }
+}
+
+void SetThreadName(const char* thread_name) {
+  bool hasAt = false;
+  bool hasDot = false;
+  const char* s = thread_name;
+  while (*s) {
+    if (*s == '.') {
+      hasDot = true;
+    } else if (*s == '@') {
+      hasAt = true;
+    }
+    s++;
+  }
+  const int len = s - thread_name;
+  if (len < 15 || hasAt || !hasDot) {
+    s = thread_name;
+  } else {
+    s = thread_name + len - 15;
+  }
+  // pthread_setname_np fails rather than truncating long strings.
+  char buf[16];       // MAX_TASK_COMM_LEN=16 is hard-coded into bionic
+  strlcpy(buf, s, sizeof(buf)-1);
+  errno = pthread_setname_np(pthread_self(), buf);
+  if (errno != 0) {
+    ALOGW("Unable to set the name of current thread to '%s'", buf);
+  }
+}
+
+// Utility routine to fork zygote and specialize the child process.
+static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
+                                     jint debug_flags, jobjectArray javaRlimits,
+                                     jlong permittedCapabilities, jlong effectiveCapabilities,
+                                     jint mount_external,
+                                     jstring java_se_info, jstring java_se_name,
+                                     bool is_system_server, jintArray fdsToClose) {
+  SetSigChldHandler();
+
+  pid_t pid = fork();
+
+  if (pid == 0) {
+    // The child process.
+    gMallocLeakZygoteChild = 1;
+
+    // Clean up any descriptors which must be closed immediately
+    DetachDescriptors(env, fdsToClose);
+
+    // Keep capabilities across UID change, unless we're staying root.
+    if (uid != 0) {
+      EnableKeepCapabilities(env);
+    }
+
+    DropCapabilitiesBoundingSet(env);
+
+    if (!MountEmulatedStorage(uid, mount_external)) {
+      ALOGW("Failed to mount emulated storage: %d", errno);
+      if (errno == ENOTCONN || errno == EROFS) {
+        // When device is actively encrypting, we get ENOTCONN here
+        // since FUSE was mounted before the framework restarted.
+        // When encrypted device is booting, we get EROFS since
+        // FUSE hasn't been created yet by init.
+        // In either case, continue without external storage.
+      } else {
+        ALOGE("Cannot continue without emulated storage");
+        RuntimeAbort(env);
+      }
+    }
+
+    SetGids(env, javaGids);
+
+    SetRLimits(env, javaRlimits);
+
+    int rc = setresgid(gid, gid, gid);
+    if (rc == -1) {
+      ALOGE("setresgid(%d) failed", gid);
+      RuntimeAbort(env);
+    }
+
+    rc = setresuid(uid, uid, uid);
+    if (rc == -1) {
+      ALOGE("setresuid(%d) failed", uid);
+      RuntimeAbort(env);
+    }
+
+#if defined(__linux__)
+    if (NeedsNoRandomizeWorkaround()) {
+        // Work around ARM kernel ASLR lossage (http://b/5817320).
+        int old_personality = personality(0xffffffff);
+        int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
+        if (new_personality == -1) {
+            ALOGW("personality(%d) failed", new_personality);
+        }
+    }
+#endif
+
+    SetCapabilities(env, permittedCapabilities, effectiveCapabilities);
+
+    SetSchedulerPolicy(env);
+
+#if defined(HAVE_ANDROID_OS)
+    {  // NOLINT(whitespace/braces)
+      const char* se_info_c_str = NULL;
+      ScopedUtfChars* se_info = NULL;
+      if (java_se_info != NULL) {
+          se_info = new ScopedUtfChars(env, java_se_info);
+          se_info_c_str = se_info->c_str();
+          if (se_info_c_str == NULL) {
+            ALOGE("se_info_c_str == NULL");
+            RuntimeAbort(env);
+          }
+      }
+      const char* se_name_c_str = NULL;
+      ScopedUtfChars* se_name = NULL;
+      if (java_se_name != NULL) {
+          se_name = new ScopedUtfChars(env, java_se_name);
+          se_name_c_str = se_name->c_str();
+          if (se_name_c_str == NULL) {
+            ALOGE("se_name_c_str == NULL");
+            RuntimeAbort(env);
+          }
+      }
+      rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
+      if (rc == -1) {
+        ALOGE("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
+              is_system_server, se_info_c_str, se_name_c_str);
+        RuntimeAbort(env);
+      }
+
+      // Make it easier to debug audit logs by setting the main thread's name to the
+      // nice name rather than "app_process".
+      if (se_info_c_str == NULL && is_system_server) {
+        se_name_c_str = "system_server";
+      }
+      if (se_info_c_str != NULL) {
+        SetThreadName(se_name_c_str);
+      }
+
+      delete se_info;
+      delete se_name;
+    }
+#else
+    UNUSED(is_system_server);
+    UNUSED(java_se_info);
+    UNUSED(java_se_name);
+#endif
+
+    UnsetSigChldHandler();
+
+    env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags);
+    if (env->ExceptionCheck()) {
+      ALOGE("Error calling post fork hooks.");
+      RuntimeAbort(env);
+    }
+  } else if (pid > 0) {
+    // the parent process
+  }
+  return pid;
+}
+}  // anonymous namespace
+
+namespace android {
+
+static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
+        JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
+        jint debug_flags, jobjectArray rlimits,
+        jint mount_external, jstring se_info, jstring se_name,
+        jintArray fdsToClose) {
+    return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
+            rlimits, 0, 0, mount_external, se_info, se_name, false, fdsToClose);
+}
+
+static jint com_android_internal_os_Zygote_nativeForkSystemServer(
+        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
+        jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities,
+        jlong effectiveCapabilities) {
+  pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
+                                      debug_flags, rlimits,
+                                      permittedCapabilities, effectiveCapabilities,
+                                      MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL);
+  if (pid > 0) {
+      // The zygote process checks whether the child process has died or not.
+      ALOGI("System server process %d has been created", pid);
+      gSystemServerPid = pid;
+      // There is a slight window that the system server process has crashed
+      // but it went unnoticed because we haven't published its pid yet. So
+      // we recheck here just to make sure that all is well.
+      int status;
+      if (waitpid(pid, &status, WNOHANG) == pid) {
+          ALOGE("System server process %d has died. Restarting Zygote!", pid);
+          RuntimeAbort(env);
+      }
+  }
+  return pid;
+}
+
+static JNINativeMethod gMethods[] = {
+    { "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;[I)I",
+      (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
+    { "nativeForkSystemServer", "(II[II[[IJJ)I",
+      (void *) com_android_internal_os_Zygote_nativeForkSystemServer }
+};
+
+int register_com_android_internal_os_Zygote(JNIEnv* env) {
+  gZygoteClass = (jclass) env->NewGlobalRef(env->FindClass(kZygoteClassName));
+  if (gZygoteClass == NULL) {
+    RuntimeAbort(env);
+  }
+  gCallPostForkChildHooks = env->GetStaticMethodID(gZygoteClass, "callPostForkChildHooks", "(I)V");
+
+  return AndroidRuntime::registerNativeMethods(env, "com/android/internal/os/Zygote",
+      gMethods, NELEM(gMethods));
+}
+}  // namespace android
+
diff --git a/include/android_runtime/AndroidRuntime.h b/include/android_runtime/AndroidRuntime.h
index 649f4c3..6f2af90 100644
--- a/include/android_runtime/AndroidRuntime.h
+++ b/include/android_runtime/AndroidRuntime.h
@@ -34,7 +34,7 @@
 class AndroidRuntime
 {
 public:
-    AndroidRuntime();
+    AndroidRuntime(char* argBlockStart, size_t argBlockSize);
     virtual ~AndroidRuntime();
 
     enum StartMode {
@@ -44,6 +44,8 @@
         Tool,
     };
 
+    void setArgv0(const char* argv0);
+
     /**
      * Register a set of methods in the specified class.
      */
@@ -120,6 +122,8 @@
 
     Vector<JavaVMOption> mOptions;
     bool mExitWithoutCleanup;
+    char* const mArgBlockStart;
+    const size_t mArgBlockLength;
 
     /* JNI JavaVM pointer */
     static JavaVM* mJavaVM;
diff --git a/libs/androidfw/BackupData.cpp b/libs/androidfw/BackupData.cpp
index 2d0f755..bd9dc76 100644
--- a/libs/androidfw/BackupData.cpp
+++ b/libs/androidfw/BackupData.cpp
@@ -78,7 +78,7 @@
     paddingSize = padding_extra(n);
     if (paddingSize > 0) {
         uint32_t padding = 0xbcbcbcbc;
-        if (DEBUG) ALOGI("writing %d padding bytes for %d", paddingSize, n);
+        if (DEBUG) ALOGI("writing %zd padding bytes for %d", paddingSize, n);
         amt = write(m_fd, &padding, paddingSize);
         if (amt != paddingSize) {
             m_status = errno;
@@ -112,7 +112,7 @@
         k = key;
     }
     if (DEBUG) {
-        ALOGD("Writing header: prefix='%s' key='%s' dataSize=%d", m_keyPrefix.string(),
+        ALOGD("Writing header: prefix='%s' key='%s' dataSize=%zu", m_keyPrefix.string(),
                 key.string(), dataSize);
     }
 
@@ -125,7 +125,7 @@
     header.keyLen = tolel(keyLen);
     header.dataSize = tolel(dataSize);
 
-    if (DEBUG) ALOGI("writing entity header, %d bytes", sizeof(entity_header_v1));
+    if (DEBUG) ALOGI("writing entity header, %zu bytes", sizeof(entity_header_v1));
     amt = write(m_fd, &header, sizeof(entity_header_v1));
     if (amt != sizeof(entity_header_v1)) {
         m_status = errno;
@@ -133,7 +133,7 @@
     }
     m_pos += amt;
 
-    if (DEBUG) ALOGI("writing entity header key, %d bytes", keyLen+1);
+    if (DEBUG) ALOGI("writing entity header key, %zd bytes", keyLen+1);
     amt = write(m_fd, k.string(), keyLen+1);
     if (amt != keyLen+1) {
         m_status = errno;
diff --git a/libs/androidfw/BackupHelpers.cpp b/libs/androidfw/BackupHelpers.cpp
index ab837ad..52dce9f 100644
--- a/libs/androidfw/BackupHelpers.cpp
+++ b/libs/androidfw/BackupHelpers.cpp
@@ -639,7 +639,7 @@
 
         // size header -- calc len in digits by actually rendering the number
         // to a string - brute force but simple
-        snprintf(sizeStr, sizeof(sizeStr), "%lld", s.st_size);
+        snprintf(sizeStr, sizeof(sizeStr), "%lld", (long long)s.st_size);
         p += write_pax_header_entry(p, "size", sizeStr);
 
         // fullname was generated above with the ustar paths
@@ -661,7 +661,7 @@
 
         // [ 124 :  12 ] size of pax extended header data
         memset(paxHeader + 124, 0, 12);
-        snprintf(paxHeader + 124, 12, "%011o", p - paxData);
+        snprintf(paxHeader + 124, 12, "%011o", (unsigned int)(p - paxData));
 
         // Checksum and write the pax block header
         calc_tar_checksum(paxHeader);
@@ -681,7 +681,10 @@
     if (!isdir) {
         off64_t toWrite = s.st_size;
         while (toWrite > 0) {
-            size_t toRead = (toWrite < BUFSIZE) ? toWrite : BUFSIZE;
+            size_t toRead = toWrite;
+            if (toRead > BUFSIZE) {
+                toRead = BUFSIZE;
+            }
             ssize_t nRead = read(fd, buf, toRead);
             if (nRead < 0) {
                 err = errno;
@@ -1095,8 +1098,8 @@
         if (name != filenames[i] || states[i].modTime_sec != state.modTime_sec
                 || states[i].modTime_nsec != state.modTime_nsec || states[i].mode != state.mode
                 || states[i].size != state.size || states[i].crc32 != states[i].crc32) {
-            fprintf(stderr, "state %zu expected={%d/%d, 0x%08x, %04o, 0x%08x, %3d} '%s'\n"
-                            "          actual={%d/%d, 0x%08x, %04o, 0x%08x, %3zu} '%s'\n", i,
+            fprintf(stderr, "state %zu expected={%d/%d, %04o, 0x%08x, 0x%08x, %3zu} '%s'\n"
+                            "          actual={%d/%d, %04o, 0x%08x, 0x%08x, %3d} '%s'\n", i,
                     states[i].modTime_sec, states[i].modTime_nsec, states[i].mode, states[i].size,
                     states[i].crc32, name.length(), filenames[i].string(),
                     state.modTime_sec, state.modTime_nsec, state.mode, state.size, state.crc32,
@@ -1194,7 +1197,7 @@
 test_read_header_and_entity(BackupDataReader& reader, const char* str)
 {
     int err;
-    int bufSize = strlen(str)+1;
+    size_t bufSize = strlen(str)+1;
     char* buf = (char*)malloc(bufSize);
     String8 string;
     int cookie = 0x11111111;
@@ -1229,9 +1232,9 @@
         err = EINVAL;
         goto finished;
     }
-    if ((int)actualSize != bufSize) {
-        fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08zx\n", bufSize,
-                actualSize);
+    if (actualSize != bufSize) {
+        fprintf(stderr, "ReadEntityHeader expected dataSize %zu got %zu\n",
+                bufSize, actualSize);
         err = EINVAL;
         goto finished;
     }
diff --git a/libs/androidfw/CursorWindow.cpp b/libs/androidfw/CursorWindow.cpp
index 2b74a33..166863c 100644
--- a/libs/androidfw/CursorWindow.cpp
+++ b/libs/androidfw/CursorWindow.cpp
@@ -210,8 +210,8 @@
     uint32_t offset = mHeader->freeOffset + padding;
     uint32_t nextFreeOffset = offset + size;
     if (nextFreeOffset > mSize) {
-        ALOGW("Window is full: requested allocation %d bytes, "
-                "free space %d bytes, window size %d bytes",
+        ALOGW("Window is full: requested allocation %zu bytes, "
+                "free space %zu bytes, window size %zu bytes",
                 size, freeSpace(), mSize);
         return 0;
     }
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 652cd4a..1ffe665 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -5996,12 +5996,12 @@
 
                         uintptr_t esize = dtohs(ent->size);
                         if ((esize&0x3) != 0) {
-                            printf("NON-INTEGER ResTable_entry SIZE: 0x%x\n", esize);
+                            printf("NON-INTEGER ResTable_entry SIZE: %p\n", (void *)esize);
                             continue;
                         }
                         if ((thisOffset+esize) > typeSize) {
-                            printf("ResTable_entry OUT OF BOUNDS: 0x%x+0x%x+0x%x (size is 0x%x)\n",
-                                   entriesStart, thisOffset, esize, typeSize);
+                            printf("ResTable_entry OUT OF BOUNDS: 0x%x+0x%x+%p (size is 0x%x)\n",
+                                   entriesStart, thisOffset, (void *)esize, typeSize);
                             continue;
                         }
 
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index b2148b0..442e9ba 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -36,6 +36,7 @@
 }
 
 Patch::~Patch() {
+    delete[] vertices;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
index 8a44604..2f2debc 100644
--- a/libs/hwui/PatchCache.cpp
+++ b/libs/hwui/PatchCache.cpp
@@ -119,6 +119,17 @@
 
 void PatchCache::removeDeferred(Res_png_9patch* patch) {
     Mutex::Autolock _l(mLock);
+
+    // Assert that patch is not already garbage
+    size_t count = mGarbage.size();
+    for (size_t i = 0; i < count; i++) {
+        if (patch == mGarbage[i]) {
+            patch = NULL;
+            break;
+        }
+    }
+    LOG_ALWAYS_FATAL_IF(patch == NULL);
+
     mGarbage.push(patch);
 }
 
@@ -143,8 +154,8 @@
     for (size_t i = 0; i < patchesToRemove.size(); i++) {
         const patch_pair_t& pair = patchesToRemove[i];
 
-        // Add a new free block to the list
-        const Patch* patch = pair.getSecond();
+        // Release the patch and mark the space in the free list
+        Patch* patch = pair.getSecond();
         BufferBlock* block = new BufferBlock(patch->offset, patch->getSize());
         block->next = mFreeBlocks;
         mFreeBlocks = block;
@@ -152,6 +163,7 @@
         mSize -= patch->getSize();
 
         mCache.remove(*pair.getFirst());
+        delete patch;
     }
 
 #if DEBUG_PATCHES
@@ -216,6 +228,7 @@
         } else {
             mFreeBlocks = block->next;
         }
+        delete block;
     } else {
         // Resize the block now that it's occupied
         block->offset += size;
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index d276a29..77292bf 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -31,9 +31,9 @@
     ALOGD("ResourceCache: cacheReport:");
     for (size_t i = 0; i < mCache->size(); ++i) {
         ResourceReference* ref = mCache->valueAt(i);
-        ALOGD("  ResourceCache: mCache(%d): resource, ref = 0x%p, 0x%p",
+        ALOGD("  ResourceCache: mCache(%zu): resource, ref = 0x%p, 0x%p",
                 i, mCache->keyAt(i), mCache->valueAt(i));
-        ALOGD("  ResourceCache: mCache(%d): refCount, recycled, destroyed, type = %d, %d, %d, %d",
+        ALOGD("  ResourceCache: mCache(%zu): refCount, recycled, destroyed, type = %d, %d, %d, %d",
                 i, ref->refCount, ref->recycled, ref->destroyed, ref->resourceType);
     }
 }
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index cc6d0cd..5bdb18a 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -108,7 +108,7 @@
      * Returns the current clip in local coordinates. The clip rect is
      * transformed by the inverse transform matrix.
      */
-    const Rect& getLocalClip();
+    ANDROID_API const Rect& getLocalClip();
 
     /**
      * Resets the clip to the specified rect.
diff --git a/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c b/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c
index 06b477f..57c0320 100644
--- a/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c
+++ b/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c
@@ -32,7 +32,7 @@
 struct usb_device *sDevice = NULL;
 
 static void* read_thread(void* arg) {
-    int endpoint = (int)arg;
+    int endpoint = (int)(uintptr_t)arg;
     int ret = 0;
 
     while (sDevice && ret >= 0) {
@@ -52,7 +52,7 @@
 }
 
 static void* write_thread(void* arg) {
-    int endpoint = (int)arg;
+    int endpoint = (int)(uintptr_t)arg;
     int ret = 0;
 
     while (ret >= 0) {
@@ -136,11 +136,11 @@
             }
 
             if ((ep1->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
-                pthread_create(&th, NULL, read_thread, (void *)ep1->bEndpointAddress);
-                pthread_create(&th, NULL, write_thread, (void *)ep2->bEndpointAddress);
+                pthread_create(&th, NULL, read_thread, (void *)(uintptr_t)ep1->bEndpointAddress);
+                pthread_create(&th, NULL, write_thread, (void *)(uintptr_t)ep2->bEndpointAddress);
             } else {
-                pthread_create(&th, NULL, read_thread, (void *)ep2->bEndpointAddress);
-                pthread_create(&th, NULL, write_thread, (void *)ep1->bEndpointAddress);
+                pthread_create(&th, NULL, read_thread, (void *)(uintptr_t)ep2->bEndpointAddress);
+                pthread_create(&th, NULL, write_thread, (void *)(uintptr_t)ep1->bEndpointAddress);
             }
         } else {
             printf("Found possible android device - attempting to switch to accessory mode\n");
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index 543cb6c..854ee79 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -84,7 +84,7 @@
         jbyteArray byteArrayObj = env->NewByteArray(size);
         env->DeleteLocalRef(env->GetObjectClass(mDataSource));
         env->DeleteLocalRef(env->GetObjectClass(byteArrayObj));
-        ssize_t numread = env->CallIntMethod(mDataSource, mReadMethod, offset, byteArrayObj, size);
+        ssize_t numread = env->CallIntMethod(mDataSource, mReadMethod, offset, byteArrayObj, (jint)size);
         env->GetByteArrayRegion(byteArrayObj, 0, size, (jbyte*) buffer);
         env->DeleteLocalRef(byteArrayObj);
         if (env->ExceptionCheck()) {
@@ -627,7 +627,7 @@
     env->CallVoidMethod(
             cryptoInfoObj,
             gFields.cryptoInfoSetID,
-            numSubSamples,
+            (jint)numSubSamples,
             numBytesOfPlainDataObj,
             numBytesOfEncryptedDataObj,
             keyObj,
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 72ce3cc..8129c0d 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -17,11 +17,12 @@
 #define LOG_TAG "MtpDatabaseJNI"
 #include "utils/Log.h"
 
-#include <stdio.h>
 #include <assert.h>
-#include <limits.h>
-#include <unistd.h>
 #include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdio.h>
+#include <unistd.h>
 
 #include "jni.h"
 #include "JNIHelp.h"
@@ -388,7 +389,7 @@
         // release date is stored internally as just the year
         if (property == MTP_PROPERTY_ORIGINAL_RELEASE_DATE) {
             char    date[20];
-            snprintf(date, sizeof(date), "%04lld0101T000000", longValue);
+            snprintf(date, sizeof(date), "%04" PRId64 "0101T000000", longValue);
             packet.putString(date);
             goto out;
         }
@@ -645,7 +646,7 @@
     return result;
 }
 
-MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty property) {
+MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty /*property*/) {
     return -1;
 }
 
@@ -1090,7 +1091,7 @@
 }
 
 static jstring
-android_mtp_MtpPropertyGroup_format_date_time(JNIEnv *env, jobject thiz, jlong seconds)
+android_mtp_MtpPropertyGroup_format_date_time(JNIEnv *env, jobject /*thiz*/, jlong seconds)
 {
     char    date[20];
     formatDateTime(seconds, date, sizeof(date));
diff --git a/packages/InputDevices/res/raw/keyboard_layout_arabic.kcm b/packages/InputDevices/res/raw/keyboard_layout_arabic.kcm
new file mode 100644
index 0000000..2a95cfe
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_arabic.kcm
@@ -0,0 +1,319 @@
+# 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.
+
+#
+# Arabic (US-101 keys) keyboard layout.
+#
+
+type OVERLAY
+
+### ROW 1
+
+key GRAVE {
+    label:                              '`'
+    base, capslock:                     '\u0630'
+    shift:                              '\u0651'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '\u0661'
+    shift:                              '!'
+    capslock:                           '1'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '\u0662'
+    shift:                              '@'
+    capslock:                           '2'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '\u0663'
+    shift:                              '#'
+    capslock:                           '3'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '\u0664'
+    shift:                              '$'
+    capslock:                           '4'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '\u0665'
+    shift:                              '%'
+    capslock:                           '5'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '\u0666'
+    shift:                              '^'
+    capslock:                           '6'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '\u0667'
+    shift:                              '&'
+    capslock:                           '7'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '\u0668'
+    shift:                              '*'
+    capslock:                           '8'
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '\u0669'
+    shift:                              '('
+    capslock:                           '9'
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '\u0660'
+    shift:                              ')'
+    capslock:                           '0'
+}
+
+key MINUS {
+    label:                              '-'
+    base, capslock:                     '-'
+    shift:                              '_'
+}
+
+key EQUALS {
+    label:                              '='
+    base, capslock:                     '='
+    shift:                              '+'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base, capslock:                     '\u0636'
+    shift:                              '\u064e'
+}
+
+key W {
+    label:                              'W'
+    base, capslock:                     '\u0635'
+    shift:                              '\u064b'
+}
+
+key E {
+    label:                              'E'
+    base, capslock:                     '\u062b'
+    shift:                              '\u064f'
+}
+
+key R {
+    label:                              'R'
+    base, capslock:                     '\u0642'
+    shift:                              '\u064c'
+}
+
+key T {
+    label:                              'T'
+    base, capslock:                     '\u0641'
+    shift:                              '\ufef9'
+}
+
+key Y {
+    label:                              'Y'
+    base, capslock:                     '\u063a'
+    shift:                              '\u0625'
+}
+
+key U {
+    label:                              'U'
+    base, capslock:                     '\u0639'
+    shift:                              '\u2018'
+}
+
+key I {
+    label:                              'I'
+    base, capslock:                     '\u0647'
+    shift:                              '\u00f7'
+}
+
+key O {
+    label:                              'O'
+    base, capslock:                     '\u062e'
+    shift:                              '\u00d7'
+}
+
+key P {
+    label:                              'P'
+    base, capslock:                     '\u062d'
+    shift:                              '\u061b'
+}
+
+key LEFT_BRACKET {
+    label:                              '['
+    base, capslock:                     '\u062c'
+    shift:                              '<'
+}
+
+key RIGHT_BRACKET {
+    label:                              ']'
+    base, capslock:                     '\u062f'
+    shift:                              '>'
+}
+
+key BACKSLASH {
+    label:                              '\\'
+    base, capslock:                     '\\'
+    shift:                              '|'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base, capslock:                     '\u0634'
+    shift:                              '\u0650'
+}
+
+key S {
+    label:                              'S'
+    base, capslock:                     '\u0633'
+    shift:                              '\u064d'
+}
+
+key D {
+    label:                              'D'
+    base, capslock:                     '\u064a'
+    shift:                              ']'
+}
+
+key F {
+    label:                              'F'
+    base, capslock:                     '\u0628'
+    shift:                              '['
+}
+
+key G {
+    label:                              'G'
+    base, capslock:                     '\u0644'
+    shift:                              '\ufef7'
+}
+
+key H {
+    label:                              'H'
+    base, capslock:                     '\u0627'
+    shift:                              '\u0623'
+}
+
+key J {
+    label:                              'J'
+    base, capslock:                     '\u062a'
+    shift:                              '\u0640'
+}
+
+key K {
+    label:                              'K'
+    base, capslock:                     '\u0646'
+    shift:                              '\u060c'
+}
+
+key L {
+    label:                              'L'
+    base, capslock:                     '\u0645'
+    shift:                              '/'
+}
+
+key SEMICOLON {
+    label:                              ';'
+    base, capslock:                     '\u0643'
+    shift:                              ':'
+}
+
+key APOSTROPHE {
+    label:                              '\''
+    base, capslock:                     '\u0637'
+    shift:                              '"'
+}
+
+### ROW 4
+
+key Z {
+    label:                              'Z'
+    base, capslock:                     '\u0626'
+    shift:                              '~'
+}
+
+key X {
+    label:                              'X'
+    base, capslock:                     '\u0621'
+    shift:                              '\u0652'
+}
+
+key C {
+    label:                              'C'
+    base, capslock:                     '\u0624'
+    shift:                              '}'
+}
+
+key V {
+    label:                              'V'
+    base, capslock:                     '\u0631'
+    shift:                              '{'
+}
+
+key B {
+    label:                              'B'
+    base, capslock:                     '\ufefb'
+    shift:                              '\ufef5'
+}
+
+key N {
+    label:                              'N'
+    base, capslock:                     '\u0649'
+    shift:                              '\u0622'
+}
+
+key M {
+    label:                              'M'
+    base, capslock:                     '\u0629'
+    shift:                              '\u2019'
+}
+
+key COMMA {
+    label:                              ','
+    base, capslock:                     '\u0648'
+    shift:                              ','
+}
+
+key PERIOD {
+    label:                              '.'
+    base, capslock:                     '\u0632'
+    shift:                              '.'
+}
+
+key SLASH {
+    label:                              '/'
+    base, capslock:                     '\u0638'
+    shift:                              '\u061f'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_greek.kcm b/packages/InputDevices/res/raw/keyboard_layout_greek.kcm
new file mode 100644
index 0000000..a7684e1
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_greek.kcm
@@ -0,0 +1,338 @@
+# 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.
+
+#
+# Greek (EU based) keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              '`'
+    base, capslock:                     '`'
+    shift:                              '~'
+}
+
+key 1 {
+    label:                              '1'
+    base, capslock:                     '1'
+    shift:                              '!'
+}
+
+key 2 {
+    label:                              '2'
+    base, capslock:                     '2'
+    shift:                              '@'
+    ralt:                               '\u00b2'
+}
+
+key 3 {
+    label:                              '3'
+    base, capslock:                     '3'
+    shift:                              '#'
+    ralt:                               '\u00b3'
+}
+
+key 4 {
+    label:                              '4'
+    base, capslock:                     '4'
+    shift:                              '$'
+    ralt:                               '\u00a3'
+}
+
+key 5 {
+    label:                              '5'
+    base, capslock:                     '5'
+    shift:                              '%'
+    ralt:                               '\u00a7'
+}
+
+key 6 {
+    label:                              '6'
+    base, capslock:                     '6'
+    shift:                              '^'
+    ralt:                               '\u00b6'
+}
+
+key 7 {
+    label:                              '7'
+    base, capslock:                     '7'
+    shift:                              '&'
+}
+
+key 8 {
+    label:                              '8'
+    base, capslock:                     '8'
+    shift:                              '*'
+    ralt:                               '\u00a4'
+}
+
+key 9 {
+    label:                              '9'
+    base, capslock:                     '9'
+    shift:                              '('
+    ralt:                               '\u00a6'
+}
+
+key 0 {
+    label:                              '0'
+    base, capslock:                     '0'
+    shift:                              ')'
+    ralt:                               '\u00b0'
+}
+
+key MINUS {
+    label:                              '-'
+    base, capslock:                     '-'
+    shift:                              '_'
+    ralt:                               '\u00b1'
+}
+
+key EQUALS {
+    label:                              '='
+    base, capslock:                     '='
+    shift:                              '+'
+    ralt:                               '\u00bd'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base, capslock:                     ';'
+    shift:                              ':'
+}
+
+key W {
+    label:                              'W'
+    base, capslock:                     '\u03c2'
+    shift:                              '\u0385'
+}
+
+key E {
+    label:                              'E'
+    base:                               '\u03b5'
+    shift, capslock:                    '\u0395'
+    ralt:                               '\u20ac'
+}
+
+key R {
+    label:                              'R'
+    base:                               '\u03c1'
+    shift, capslock:                    '\u03a1'
+    ralt:                               '\u00ae'
+}
+
+key T {
+    label:                              'T'
+    base:                               '\u03c4'
+    shift, capslock:                    '\u03a4'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               '\u03c5'
+    shift, capslock:                    '\u03a5'
+    ralt:                               '\u00a5'
+}
+
+key U {
+    label:                              'U'
+    base:                               '\u03b8'
+    shift, capslock:                    '\u0398'
+}
+
+key I {
+    label:                              'I'
+    base:                               '\u03b9'
+    shift, capslock:                    '\u0399'
+}
+
+key O {
+    label:                              'O'
+    base:                               '\u03bf'
+    shift, capslock:                    '\u039f'
+}
+
+key P {
+    label:                              'P'
+    base:                               '\u03c0'
+    shift, capslock:                    '\u03a0'
+}
+
+key LEFT_BRACKET {
+    label:                              '['
+    base, capslock:                     '['
+    shift:                              '{'
+    ralt:                               '\u00ab'
+}
+
+key RIGHT_BRACKET {
+    label:                              ']'
+    base, capslock:                     ']'
+    shift:                              '}'
+    ralt:                               '\u00bb'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               '\u03b1'
+    shift, capslock:                    '\u0391'
+}
+
+key S {
+    label:                              'S'
+    base:                               '\u03c3'
+    shift, capslock:                    '\u03a3'
+}
+
+key D {
+    label:                              'D'
+    base:                               '\u03b4'
+    shift, capslock:                    '\u0394'
+}
+
+key F {
+    label:                              'F'
+    base:                               '\u03c6'
+    shift, capslock:                    '\u03a6'
+}
+
+key G {
+    label:                              'G'
+    base:                               '\u03b3'
+    shift, capslock:                    '\u0393'
+}
+
+key H {
+    label:                              'H'
+    base:                               '\u03b7'
+    shift, capslock:                    '\u0397'
+}
+
+key J {
+    label:                              'J'
+    base:                               '\u03be'
+    shift, capslock:                    '\u039e'
+}
+
+key K {
+    label:                              'K'
+    base:                               '\u03ba'
+    shift, capslock:                    '\u039a'
+}
+
+key L {
+    label:                              'L'
+    base:                               '\u03bb'
+    shift, capslock:                    '\u039b'
+}
+
+key SEMICOLON {
+    label:                              ';'
+    base, capslock:                     '\u0301'
+#should be \u0384 (greek tonos)
+    shift:                              '\u0308'
+    ralt:                               '\u0385'
+}
+
+key APOSTROPHE {
+    label:                              '\''
+    base, capslock:                     '\''
+    shift:                              '"'
+}
+
+key BACKSLASH {
+    label:                              '\\'
+    base, capslock:                     '\\'
+    shift:                              '|'
+    ralt:                               '\u00ac'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '<'
+    base, capslock:                     '<'
+    shift:                              '>'
+    ralt:                               '\\'
+    shift+ralt:                         '|'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               '\u03b6'
+    shift, capslock:                    '\u0396'
+}
+
+key X {
+    label:                              'X'
+    base:                               '\u03c7'
+    shift, capslock:                    '\u03a7'
+}
+
+key C {
+    label:                              'C'
+    base:                               '\u03c8'
+    shift, capslock:                    '\u03a8'
+    ralt:                               '\u00a9'
+}
+
+key V {
+    label:                              'V'
+    base:                               '\u03c9'
+    shift, capslock:                    '\u03a9'
+}
+
+key B {
+    label:                              'B'
+    base:                               '\u03b2'
+    shift, capslock:                    '\u0392'
+}
+
+key N {
+    label:                              'N'
+    base:                               '\u03bd'
+    shift, capslock:                    '\u039d'
+}
+
+key M {
+    label:                              'M'
+    base:                               '\u03bc'
+    shift, capslock:                    '\u039c'
+}
+
+key COMMA {
+    label:                              ','
+    base, capslock:                     ','
+    shift:                              '<'
+}
+
+key PERIOD {
+    label:                              '.'
+    base, capslock:                     '.'
+    shift:                              '>'
+}
+
+key SLASH {
+    label:                              '/'
+    base, capslock:                     '/'
+    shift:                              '?'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_hebrew.kcm b/packages/InputDevices/res/raw/keyboard_layout_hebrew.kcm
new file mode 100644
index 0000000..cd3a4b9
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_hebrew.kcm
@@ -0,0 +1,341 @@
+# 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.
+
+#
+# Hebrew (based EU) keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              '`'
+    base:                               ';'
+    shift:                              '~'
+    shift+capslock:                     '\u05b0'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '1'
+    shift:                              '!'
+    shift+capslock:                     '\u05b1'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '2'
+    shift:                              '@'
+    shift+capslock:                     '\u05b2'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '3'
+    shift:                              '#'
+    shift+capslock:                     '\u05b3'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '4'
+    shift:                              '$'
+    ralt:                               '\u20aa'
+    shift+capslock:                     '\u05b4'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '5'
+    shift:                              '%'
+    shift+capslock:                     '\u05b5'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '6'
+    shift:                              '^'
+    shift+capslock:                     '\u05b6'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '7'
+    shift:                              '&'
+    shift+capslock:                     '\u05b7'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '8'
+    shift:                              '*'
+    shift+capslock:                     '\u05b8'
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '9'
+    shift:                              '('
+    shift+capslock:                     '\u05c2'
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '0'
+    shift:                              ')'
+    shift+capslock:                     '\u05c1'
+}
+
+key MINUS {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+    ralt:                               '\u05bf'
+    shift+capslock:                     '\u05b9'
+}
+
+key EQUALS {
+    label:                              '='
+    base:                               '='
+    shift:                              '+'
+    shift+capslock:                     '\u05bc'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               '/'
+    shift, capslock:                    'Q'
+}
+
+key W {
+    label:                              'W'
+    base:                               '\u0027'
+    shift, capslock:                    'W'
+}
+
+key E {
+    label:                              'E'
+    base:                               '\u05e7'
+    shift, capslock:                    'E'
+    ralt:                               '\u20ac'
+}
+
+key R {
+    label:                              'R'
+    base:                               '\u05e8'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               '\u05d0'
+    shift, capslock:                    'T'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               '\u05d8'
+    shift, capslock:                    'Y'
+}
+
+key U {
+    label:                              'U'
+    base:                               '\u05d5'
+    shift, capslock:                    'U'
+    ralt:                               '\u05f0'
+}
+
+key I {
+    label:                              'I'
+    base:                               '\u05df'
+    shift, capslock:                    'I'
+}
+
+key O {
+    label:                              'O'
+    base:                               '\u05dd'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               '\u05e4'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '['
+    base, capslock:                     '['
+    shift:                              '{'
+}
+
+key RIGHT_BRACKET {
+    label:                              ']'
+    base, capslock:                     ']'
+    shift:                              '}'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               '\u05e9'
+    shift, capslock:                    'A'
+}
+
+key S {
+    label:                              'S'
+    base:                               '\u05d3'
+    shift, capslock:                    'S'
+}
+
+key D {
+    label:                              'D'
+    base:                               '\u05d2'
+    shift, capslock:                    'D'
+}
+
+key F {
+    label:                              'F'
+    base:                               '\u05db'
+    shift, capslock:                    'F'
+}
+
+key G {
+    label:                              'G'
+    base:                               '\u05e2'
+    shift, capslock:                    'G'
+}
+
+key H {
+    label:                              'H'
+    base:                               '\u05d9'
+    shift, capslock:                    'H'
+    ralt:                               '\u05f2'
+}
+
+key J {
+    label:                              'J'
+    base:                               '\u05d7'
+    shift, capslock:                    'J'
+    ralt:                               '\u05f1'
+}
+
+key K {
+    label:                              'K'
+    base:                               '\u05dc'
+    shift, capslock:                    'K'
+}
+
+key L {
+    label:                              'L'
+    base:                               '\u05da'
+    shift, capslock:                    'L'
+}
+
+key SEMICOLON {
+    label:                              ';'
+    base:                               '\u05e3'
+    shift:                              ':'
+    capslock:                           ';'
+}
+
+key APOSTROPHE {
+    label:                              '\''
+    base:                               ','
+    shift:                              '"'
+    capslock:                           '\''
+}
+
+key BACKSLASH {
+    label:                              '\\'
+    base:                               '\\'
+    shift:                              '|'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '\\'
+    base, capslock:                     '\\'
+    shift:                              '|'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               '\u05d6'
+    shift, capslock:                    'Z'
+}
+
+key X {
+    label:                              'X'
+    base:                               '\u05e1'
+    shift, capslock:                    'X'
+}
+
+key C {
+    label:                              'C'
+    base:                               '\u05d1'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               '\u05d4'
+    shift, capslock:                    'V'
+}
+
+key B {
+    label:                              'B'
+    base:                               '\u05e0'
+    shift, capslock:                    'B'
+}
+
+key N {
+    label:                              'N'
+    base:                               '\u05de'
+    shift, capslock:                    'N'
+}
+
+key M {
+    label:                              'M'
+    base:                               '\u05e6'
+    shift, capslock:                    'M'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               '\u05ea'
+    shift:                              '<'
+    capslock:                           ','
+}
+
+key PERIOD {
+    label:                              '.'
+    base:                               '\u05e5'
+    shift:                              '>'
+    capslock:                           '.'
+}
+
+key SLASH {
+    label:                              '/'
+    base:                               '.'
+    shift:                              '?'
+    capslock:                           '/'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_lithuanian.kcm b/packages/InputDevices/res/raw/keyboard_layout_lithuanian.kcm
new file mode 100644
index 0000000..72ca333
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_lithuanian.kcm
@@ -0,0 +1,338 @@
+# 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.
+
+#
+# Lithuanian (EU based) keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              '`'
+    base:                               '`'
+    shift:                              '~'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '\u0105'
+    shift, capslock:                    '\u0104'
+    ralt:                               '1'
+    shift+ralt:                         '!'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '\u010d'
+    shift, capslock:                    '\u010c'
+    ralt:                               '2'
+    shift+ralt:                         '@'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '\u0119'
+    shift, capslock:                    '\u0118'
+    ralt:                               '3'
+    shift+ralt:                         '#'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '\u0117'
+    shift, capslock:                    '\u0116'
+    ralt:                               '4'
+    shift+ralt:                         '$'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '\u012f'
+    shift, capslock:                    '\u012e'
+    ralt:                               '5'
+    shift+ralt:                         '%'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '\u0161'
+    shift, capslock:                    '\u0160'
+    ralt:                               '6'
+    shift+ralt:                         '\u0302'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '\u0173'
+    shift, capslock:                    '\u0172'
+    ralt:                               '7'
+    shift+ralt:                         '&'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '\u016b'
+    shift, capslock:                    '\u016a'
+    ralt:                               '8'
+    shift+ralt:                         '*'
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '9'
+    shift:                              '('
+    ralt:                               '9'
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '0'
+    shift:                              ')'
+    ralt:                               '0'
+}
+
+key MINUS {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+}
+
+key EQUALS {
+    label:                              '='
+    base:                               '\u017e'
+    shift, capslock:                    '\u017d'
+    ralt:                               '='
+    shift+ralt:                         '+'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               'q'
+    shift, capslock:                    'Q'
+}
+
+key W {
+    label:                              'W'
+    base:                               'w'
+    shift, capslock:                    'W'
+}
+
+key E {
+    label:                              'E'
+    base:                               'e'
+    shift, capslock:                    'E'
+    ralt:                               '\u20ac'
+}
+
+key R {
+    label:                              'R'
+    base:                               'r'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               't'
+    shift, capslock:                    'T'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               'y'
+    shift, capslock:                    'Y'
+}
+
+key U {
+    label:                              'U'
+    base:                               'u'
+    shift, capslock:                    'U'
+}
+
+key I {
+    label:                              'I'
+    base:                               'i'
+    shift, capslock:                    'I'
+}
+
+key O {
+    label:                              'O'
+    base:                               'o'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               'p'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '['
+    base:                               '['
+    shift:                              '{'
+}
+
+key RIGHT_BRACKET {
+    label:                              ']'
+    base:                               ']'
+    shift:                              '}'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               'a'
+    shift, capslock:                    'A'
+}
+
+key S {
+    label:                              'S'
+    base:                               's'
+    shift, capslock:                    'S'
+}
+
+key D {
+    label:                              'D'
+    base:                               'd'
+    shift, capslock:                    'D'
+}
+
+key F {
+    label:                              'F'
+    base:                               'f'
+    shift, capslock:                    'F'
+}
+
+key G {
+    label:                              'G'
+    base:                               'g'
+    shift, capslock:                    'G'
+}
+
+key H {
+    label:                              'H'
+    base:                               'h'
+    shift, capslock:                    'H'
+}
+
+key J {
+    label:                              'J'
+    base:                               'j'
+    shift, capslock:                    'J'
+}
+
+key K {
+    label:                              'K'
+    base:                               'k'
+    shift, capslock:                    'K'
+}
+
+key L {
+    label:                              'L'
+    base:                               'l'
+    shift, capslock:                    'L'
+}
+
+key SEMICOLON {
+    label:                              ';'
+    base:                               ';'
+    shift:                              ':'
+}
+
+key APOSTROPHE {
+    label:                              '\''
+    base:                               '\''
+    shift:                              '"'
+}
+
+key BACKSLASH {
+    label:                              '\\'
+    base:                               '\\'
+    shift:                              '|'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '\\'
+    base:                               '\\'
+    shift:                              '|'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               'z'
+    shift, capslock:                    'Z'
+}
+
+key X {
+    label:                              'X'
+    base:                               'x'
+    shift, capslock:                    'X'
+}
+
+key C {
+    label:                              'C'
+    base:                               'c'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               'v'
+    shift, capslock:                    'V'
+}
+
+key B {
+    label:                              'B'
+    base:                               'b'
+    shift, capslock:                    'B'
+}
+
+key N {
+    label:                              'N'
+    base:                               'n'
+    shift, capslock:                    'N'
+}
+
+key M {
+    label:                              'M'
+    base:                               'm'
+    shift, capslock:                    'M'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               ','
+    shift:                              '<'
+}
+
+key PERIOD {
+    label:                              '.'
+    base:                               '.'
+    shift:                              '>'
+}
+
+key SLASH {
+    label:                              '/'
+    base:                               '/'
+    shift:                              '?'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_spanish_latin.kcm b/packages/InputDevices/res/raw/keyboard_layout_spanish_latin.kcm
new file mode 100644
index 0000000..16eb53f
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_spanish_latin.kcm
@@ -0,0 +1,325 @@
+# 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.
+
+#
+# Spanish (Latin) (EU based) keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              '|'
+    base:                               '|'
+    shift:                              '\u00ba'
+    ralt:                               '\u00ac'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '1'
+    shift:                              '!'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '2'
+    shift:                              '"'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '3'
+    shift:                              '#'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '4'
+    shift:                              '$'
+
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '5'
+    shift:                              '%'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '6'
+    shift:                              '&'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '7'
+    shift:                              '/'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '8'
+    shift:                              '('
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '9'
+    shift:                              ')'
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '0'
+    shift:                              '='
+}
+
+key MINUS {
+    label:                              '\''
+    base:                               '\''
+    shift:                              '?'
+    ralt:                               '\\'
+}
+
+key EQUALS {
+    label:                              '\u00bf'
+    base:                               '\u00bf'
+    shift:                              '\u00a1'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               'q'
+    shift, capslock:                    'Q'
+    ralt:                               '@'
+}
+
+key W {
+    label:                              'W'
+    base:                               'w'
+    shift, capslock:                    'W'
+}
+
+key E {
+    label:                              'E'
+    base:                               'e'
+    shift, capslock:                    'E'
+}
+
+key R {
+    label:                              'R'
+    base:                               'r'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               't'
+    shift, capslock:                    'T'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               'y'
+    shift, capslock:                    'Y'
+}
+
+key U {
+    label:                              'U'
+    base:                               'u'
+    shift, capslock:                    'U'
+}
+
+key I {
+    label:                              'I'
+    base:                               'i'
+    shift, capslock:                    'I'
+}
+
+key O {
+    label:                              'O'
+    base:                               'o'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               'p'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '\u00b4'
+    base:                               '\u0301'
+    shift:                              '\u0308'
+    ralt:                               '['
+}
+
+key RIGHT_BRACKET {
+    label:                              '+'
+    base:                               '+'
+    shift:                              '*'
+    ralt:                               '\u0303'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               'a'
+    shift, capslock:                    'A'
+}
+
+key S {
+    label:                              'S'
+    base:                               's'
+    shift, capslock:                    'S'
+}
+
+key D {
+    label:                              'D'
+    base:                               'd'
+    shift, capslock:                    'D'
+}
+
+key F {
+    label:                              'F'
+    base:                               'f'
+    shift, capslock:                    'F'
+}
+
+key G {
+    label:                              'G'
+    base:                               'g'
+    shift, capslock:                    'G'
+}
+
+key H {
+    label:                              'H'
+    base:                               'h'
+    shift, capslock:                    'H'
+}
+
+key J {
+    label:                              'J'
+    base:                               'j'
+    shift, capslock:                    'J'
+}
+
+key K {
+    label:                              'K'
+    base:                               'k'
+    shift, capslock:                    'K'
+}
+
+key L {
+    label:                              'L'
+    base:                               'l'
+    shift, capslock:                    'L'
+}
+
+key SEMICOLON {
+    label:                              '\u00d1'
+    base:                               '\u00f1'
+    shift, capslock:                    '\u00d1'
+}
+
+key APOSTROPHE {
+    label:                              '{'
+    base:                               '{'
+    shift:                              '['
+    ralt:                               '\u0302'
+}
+
+key BACKSLASH {
+    label:                              '}'
+    base:                               '}'
+    shift:                              ']'
+    ralt:                               '\u0300'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '<'
+    base:                               '<'
+    shift:                              '>'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               'z'
+    shift, capslock:                    'Z'
+}
+
+key X {
+    label:                              'X'
+    base:                               'x'
+    shift, capslock:                    'X'
+}
+
+key C {
+    label:                              'C'
+    base:                               'c'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               'v'
+    shift, capslock:                    'V'
+}
+
+key B {
+    label:                              'B'
+    base:                               'b'
+    shift, capslock:                    'B'
+}
+
+key N {
+    label:                              'N'
+    base:                               'n'
+    shift, capslock:                    'N'
+}
+
+key M {
+    label:                              'M'
+    base:                               'm'
+    shift, capslock:                    'M'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               ','
+    shift:                              ';'
+}
+
+key PERIOD {
+    label:                              '.'
+    base:                               '.'
+    shift:                              ':'
+}
+
+key SLASH {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+}
diff --git a/packages/InputDevices/res/values/strings.xml b/packages/InputDevices/res/values/strings.xml
index 54c18f1..6239336 100644
--- a/packages/InputDevices/res/values/strings.xml
+++ b/packages/InputDevices/res/values/strings.xml
@@ -98,4 +98,19 @@
 
     <!-- Ukrainian keyboard layout label. [CHAR LIMIT=35] -->
     <string name="keyboard_layout_ukrainian">Ukrainian</string>
+
+    <!-- Arabic keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_arabic">Arabic</string>
+
+    <!-- Greek keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_greek">Greek</string>
+
+    <!-- Hebrew keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_hebrew">Hebrew</string>
+
+    <!-- Lithuanian keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_lithuanian">Lithuanian</string>
+
+    <!-- Spanish (Latin) keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_spanish_latin">Spanish (Latin)</string>
 </resources>
diff --git a/packages/InputDevices/res/xml/keyboard_layouts.xml b/packages/InputDevices/res/xml/keyboard_layouts.xml
index 1f48a36..dc1db0b 100644
--- a/packages/InputDevices/res/xml/keyboard_layouts.xml
+++ b/packages/InputDevices/res/xml/keyboard_layouts.xml
@@ -123,4 +123,24 @@
     <keyboard-layout android:name="keyboard_layout_ukrainian"
             android:label="@string/keyboard_layout_ukrainian"
             android:keyboardLayout="@raw/keyboard_layout_ukrainian" />
+
+    <keyboard-layout android:name="keyboard_layout_arabic"
+            android:label="@string/keyboard_layout_arabic"
+            android:keyboardLayout="@raw/keyboard_layout_arabic" />
+
+    <keyboard-layout android:name="keyboard_layout_greek"
+            android:label="@string/keyboard_layout_greek"
+            android:keyboardLayout="@raw/keyboard_layout_greek" />
+
+    <keyboard-layout android:name="keyboard_layout_hebrew"
+            android:label="@string/keyboard_layout_hebrew"
+            android:keyboardLayout="@raw/keyboard_layout_hebrew" />
+
+    <keyboard-layout android:name="keyboard_layout_lithuanian"
+            android:label="@string/keyboard_layout_lithuanian"
+            android:keyboardLayout="@raw/keyboard_layout_lithuanian" />
+
+    <keyboard-layout android:name="keyboard_layout_spanish_latin"
+            android:label="@string/keyboard_layout_spanish_latin"
+            android:keyboardLayout="@raw/keyboard_layout_spanish_latin" />
 </keyboard-layouts>
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 7c0735b..4db7d4d 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -121,13 +121,14 @@
         filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
         context.registerReceiver(mBroadcastReceiver, filter);
 
+        ConnectivityManager cm = (ConnectivityManager)
+                context.getSystemService(Context.CONNECTIVITY_SERVICE);
+        mHasTelephony = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
+
         // get notified of phone state changes
         TelephonyManager telephonyManager =
                 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
         telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
-        ConnectivityManager cm = (ConnectivityManager)
-                context.getSystemService(Context.CONNECTIVITY_SERVICE);
-        mHasTelephony = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
         mContext.getContentResolver().registerContentObserver(
                 Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
                 mAirplaneModeObserver);
diff --git a/rs/java/android/renderscript/RenderScriptGL.java b/rs/java/android/renderscript/RenderScriptGL.java
index c9cbe3e..d6841c8 100644
--- a/rs/java/android/renderscript/RenderScriptGL.java
+++ b/rs/java/android/renderscript/RenderScriptGL.java
@@ -232,9 +232,13 @@
         validate();
         //android.util.Log.v("rs", "set surface " + sur + " w=" + w + ", h=" + h);
 
+        Surface s = null;
+        if (sur != null) {
+            s = new Surface(sur);
+        }
         mWidth = w;
         mHeight = h;
-        nContextSetSurfaceTexture(w, h, sur);
+        nContextSetSurface(w, h, s);
     }
 
     /**
diff --git a/services/common_time/common_time_server.cpp b/services/common_time/common_time_server.cpp
index 21e706f..3e11987 100644
--- a/services/common_time/common_time_server.cpp
+++ b/services/common_time/common_time_server.cpp
@@ -590,7 +590,7 @@
     for (i = 0; (i < src_len) && (offset < dst_len); ++i) {
         int res;
         if (0 == (i % 16)) {
-            res = snprintf(dst + offset, dst_len - offset, "\n%04x :", i);
+            res = snprintf(dst + offset, dst_len - offset, "\n%04zx :", i);
             if (res < 0)
                 break;
             offset += res;
diff --git a/services/common_time/utils.cpp b/services/common_time/utils.cpp
index ed2c77d..ddcdfe7 100644
--- a/services/common_time/utils.cpp
+++ b/services/common_time/utils.cpp
@@ -56,7 +56,7 @@
     , mHeader(header) {
     mRingBuffer = new Entry[mSize];
     if (NULL == mRingBuffer)
-        ALOGE("Failed to allocate log ring with %u entries.", mSize);
+        ALOGE("Failed to allocate log ring with %zu entries.", mSize);
 }
 
 LogRing::~LogRing() {
@@ -150,7 +150,7 @@
 
         localtime_r(&mRingBuffer[ndx].first_ts.tv_sec, &t);
         strftime(timebuf, sizeof(timebuf), kTimeFmt, &t);
-        res = snprintf(buf, sizeof(buf), "[%2d] %s.%03ld :: %s%s\n", 
+        res = snprintf(buf, sizeof(buf), "[%2zu] %s.%03ld :: %s%s\n",
                        i, timebuf,
                        mRingBuffer[ndx].first_ts.tv_usec / 1000,
                        mRingBuffer[ndx].s.string(),
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index fc64656..e3a3e17 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -759,7 +759,7 @@
                 if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
                     // Device was removed before INotify noticed.
                     ALOGW("could not get event, removed? (fd: %d size: %d bufferSize: %d "
-                            "capacity: %d errno: %d)\n",
+                            "capacity: %zu errno: %d)\n",
                             device->fd, readSize, bufferSize, capacity, errno);
                     deviceChanged = true;
                     closeDeviceLocked(device);
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 10a639e..06a57d5 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -147,7 +147,7 @@
         return false;
     }
     if (pointerCount < 1 || pointerCount > MAX_POINTERS) {
-        ALOGE("Motion event has invalid pointer count %d; value must be between 1 and %d.",
+        ALOGE("Motion event has invalid pointer count %zu; value must be between 1 and %d.",
                 pointerCount, MAX_POINTERS);
         return false;
     }
@@ -3107,7 +3107,7 @@
         dump.append(INDENT "TouchedWindows:\n");
         for (size_t i = 0; i < mTouchState.windows.size(); i++) {
             const TouchedWindow& touchedWindow = mTouchState.windows[i];
-            dump.appendFormat(INDENT2 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
+            dump.appendFormat(INDENT2 "%zu: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
                     i, touchedWindow.windowHandle->getName().string(),
                     touchedWindow.pointerIds.value,
                     touchedWindow.targetFlags);
@@ -3122,7 +3122,7 @@
             const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
             const InputWindowInfo* windowInfo = windowHandle->getInfo();
 
-            dump.appendFormat(INDENT2 "%d: name='%s', displayId=%d, "
+            dump.appendFormat(INDENT2 "%zu: name='%s', displayId=%d, "
                     "paused=%s, hasFocus=%s, hasWallpaper=%s, "
                     "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
                     "frame=[%d,%d][%d,%d], scale=%f, "
@@ -3152,7 +3152,7 @@
         dump.append(INDENT "MonitoringChannels:\n");
         for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
             const sp<InputChannel>& channel = mMonitoringChannels[i];
-            dump.appendFormat(INDENT2 "%d: '%s'\n", i, channel->getName().string());
+            dump.appendFormat(INDENT2 "%zu: '%s'\n", i, channel->getName().string());
         }
     } else {
         dump.append(INDENT "MonitoringChannels: <none>\n");
@@ -3201,7 +3201,7 @@
         dump.append(INDENT "Connections:\n");
         for (size_t i = 0; i < mConnectionsByFd.size(); i++) {
             const sp<Connection>& connection = mConnectionsByFd.valueAt(i);
-            dump.appendFormat(INDENT2 "%d: channelName='%s', windowName='%s', "
+            dump.appendFormat(INDENT2 "%zu: channelName='%s', windowName='%s', "
                     "status=%s, monitor=%s, inputPublisherBlocked=%s\n",
                     i, connection->getInputChannelName(), connection->getWindowName(),
                     connection->getStatusLabel(), toString(connection->monitor),
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 03852a5..d86fa4f 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -1992,7 +1992,7 @@
     dumpParameters(dump);
     dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
     dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
-    dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mKeyDowns.size());
+    dump.appendFormat(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size());
     dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mMetaState);
     dump.appendFormat(INDENT3 "DownTime: %lld\n", mDownTime);
 }
@@ -3372,7 +3372,7 @@
 
         for (size_t i = 0; i < mVirtualKeys.size(); i++) {
             const VirtualKey& virtualKey = mVirtualKeys.itemAt(i);
-            dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
+            dump.appendFormat(INDENT4 "%zu: scanCode=%d, keyCode=%d, "
                     "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
                     i, virtualKey.scanCode, virtualKey.keyCode,
                     virtualKey.hitLeft, virtualKey.hitRight,
@@ -6119,8 +6119,8 @@
             && mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) {
         size_t slotCount = mRawPointerAxes.slot.maxValue + 1;
         if (slotCount > MAX_SLOTS) {
-            ALOGW("MultiTouch Device %s reported %d slots but the framework "
-                    "only supports a maximum of %d slots at this time.",
+            ALOGW("MultiTouch Device %s reported %zu slots but the framework "
+                    "only supports a maximum of %zu slots at this time.",
                     getDeviceName().string(), slotCount, MAX_SLOTS);
             slotCount = MAX_SLOTS;
         }
@@ -6292,7 +6292,7 @@
         // If there are too many axes, start dropping them.
         // Prefer to keep explicitly mapped axes.
         if (mAxes.size() > PointerCoords::MAX_AXES) {
-            ALOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
+            ALOGI("Joystick '%s' has %zu axes but the framework only supports a maximum of %d.",
                     getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
             pruneAxes(true);
             pruneAxes(false);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index d895137..ade8414 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -46,6 +46,7 @@
 
 import com.android.internal.R;
 import com.android.internal.os.BinderInternal;
+import com.android.internal.os.Zygote;
 import com.android.internal.os.SamplingProfilerIntegration;
 import com.android.server.accessibility.AccessibilityManagerService;
 import com.android.server.accounts.AccountManagerService;
@@ -71,7 +72,6 @@
 import com.android.server.wm.WindowManagerService;
 
 import dalvik.system.VMRuntime;
-import dalvik.system.Zygote;
 
 import java.io.File;
 import java.util.Timer;
@@ -824,7 +824,7 @@
         if (safeMode) {
             ActivityManagerService.self().enterSafeMode();
             // Post the safe mode state in the Zygote class
-            Zygote.systemInSafeMode = true;
+            SystemServer.inSafeMode = true;
             // Disable the JIT for the system_server process
             VMRuntime.getRuntime().disableJitCompilation();
         } else {
@@ -1117,6 +1117,11 @@
     // give any timezone code room without going into negative time.
     private static final long EARLIEST_SUPPORTED_TIME = 86400 * 1000;
 
+   /**
+    * When set, all subsequent apps will be launched in safe mode.
+    */
+    public static boolean inSafeMode;
+
     /**
      * Called to initialize native system services.
      */
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 97696a5..2b0c0c9 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -38,6 +38,7 @@
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.internal.os.ProcessCpuTracker;
 import com.android.internal.os.TransferPipe;
+import com.android.internal.os.Zygote;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.MemInfoReader;
@@ -57,8 +58,6 @@
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 
-import dalvik.system.Zygote;
-
 import libcore.io.IoUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -2768,7 +2767,7 @@
             // Run the app in safe mode if its manifest requests so or the
             // system is booted in safe mode.
             if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
-                Zygote.systemInSafeMode == true) {
+                SystemServer.inSafeMode == true) {
                 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
             }
             if ("1".equals(SystemProperties.get("debug.checkjni"))) {
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index d651a62..07c2201 100755
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -1142,6 +1142,7 @@
                         // At this point, nothing else needs to be shown
                         if (DEBUG_VISBILITY) Slog.v(TAG, "Fullscreen: at " + r);
                         behindFullscreen = true;
+                        showHomeBehindStack = false;
                     } else if (isActivityOverHome(r)) {
                         if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r);
                         showHomeBehindStack = true;
@@ -2624,6 +2625,9 @@
         if (mResumedActivity == r) {
             mResumedActivity = null;
         }
+        if (mPausingActivity == r) {
+            mPausingActivity = null;
+        }
         if (mService.mFocusedActivity == r) {
             mService.mFocusedActivity = null;
         }
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
old mode 100644
new mode 100755
index 483b4a0..93de0a6
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1425,6 +1425,7 @@
             r.resultTo = null;
         }
 
+        boolean switchStackFromBg = false;
         boolean addingToTask = false;
         boolean movedHome = false;
         TaskRecord reuseTask = null;
@@ -1486,6 +1487,11 @@
                             }
                             options = null;
                         }
+                    } else {
+                        switchStackFromBg = lastStack != targetStack;
+                        if (DEBUG_TASKS) Slog.d(TAG, "Caller " + sourceRecord
+                                    + " is not top task, it may not move " + r
+                                    + " to front, switchStack=" + switchStackFromBg);
                     }
                     // If the caller has requested that the target task be
                     // reset, then do so.
@@ -1593,6 +1599,10 @@
                         // don't use that intent!)  And for paranoia, make
                         // sure we have correctly resumed the top activity.
                         if (doResume) {
+                            if (switchStackFromBg) {
+                                moveHomeStack(lastStack.isHomeStack());
+                                targetStack = lastStack;
+                            }
                             targetStack.resumeTopActivityLocked(null, options);
                         } else {
                             ActivityOptions.abort(options);
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index 4b087cc..8cd9d93 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -397,7 +397,14 @@
         return execute(builder.toString());
     }
 
-    public boolean restoreconData() {
-        return (execute("restorecondata") == 0);
+    public boolean restoreconData(String pkgName, String seinfo, int uid) {
+        StringBuilder builder = new StringBuilder("restorecondata");
+        builder.append(' ');
+        builder.append(pkgName);
+        builder.append(' ');
+        builder.append(seinfo != null ? seinfo : "!");
+        builder.append(' ');
+        builder.append(uid);
+        return (execute(builder.toString()) == 0);
     }
 }
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 5dded57..f33f7394 100755
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -393,6 +393,9 @@
     // If mac_permissions.xml was found for seinfo labeling.
     boolean mFoundPolicyFile;
 
+    // If a recursive restorecon of /data/data/<pkg> is needed.
+    private boolean mShouldRestoreconData = SELinuxMMAC.shouldRestorecon();
+
     // All available activities, for your resolving pleasure.
     final ActivityIntentResolver mActivities =
             new ActivityIntentResolver();
@@ -1486,13 +1489,6 @@
             // can downgrade to reader
             mSettings.writeLPr();
 
-            if (SELinuxMMAC.shouldRestorecon()) {
-                Slog.i(TAG, "Relabeling of /data/data and /data/user issued.");
-                if (mInstaller.restoreconData()) {
-                    SELinuxMMAC.setRestoreconDone();
-                }
-            }
-
             EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
                     SystemClock.uptimeMillis());
 
@@ -4617,6 +4613,11 @@
                     }
                 }
                 pkg.applicationInfo.dataDir = dataPath.getPath();
+                if (mShouldRestoreconData) {
+                    Slog.i(TAG, "SELinux relabeling of " + pkg.packageName + " issued.");
+                    mInstaller.restoreconData(pkg.packageName, pkg.applicationInfo.seinfo,
+                                pkg.applicationInfo.uid);
+                }
             } else {
                 if (DEBUG_PACKAGE_SCANNING) {
                     if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
@@ -11062,6 +11063,10 @@
      */
     public void scanAvailableAsecs() {
         updateExternalMediaStatusInner(true, false, false);
+        if (mShouldRestoreconData) {
+            SELinuxMMAC.setRestoreconDone();
+            mShouldRestoreconData = false;
+        }
     }
 
     /*
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index e599409..ed025e1 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -1427,6 +1427,7 @@
                     // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
                     //   system/core/run-as/run-as.c
                     //   system/core/sdcard/sdcard.c
+                    //   external/libselinux/src/android.c:package_info_init()
                     //
                     sb.setLength(0);
                     sb.append(ai.packageName);
diff --git a/services/jni/com_android_server_AlarmManagerService.cpp b/services/jni/com_android_server_AlarmManagerService.cpp
index c26a516..a58b00bce 100644
--- a/services/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/jni/com_android_server_AlarmManagerService.cpp
@@ -365,7 +365,9 @@
     int result = impl->set(type, &ts);
     if (result < 0)
     {
-        ALOGE("Unable to set alarm to %lld.%09lld: %s\n", seconds, nanoseconds, strerror(errno));
+        ALOGE("Unable to set alarm to %lld.%09lld: %s\n",
+              static_cast<long long>(seconds),
+              static_cast<long long>(nanoseconds), strerror(errno));
     }
 }
 
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index 323e0ac..1c75658 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -101,8 +101,93 @@
     /** Unknown error or not specified */
     public static final int ERROR_UNSPECIFIED              = 36;
 
+    /** Smallest valid value for call disconnect codes. */
+    public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED;
+    /** Largest valid value for call disconnect codes. */
+    public static final int MAXIMUM_VALID_VALUE = ERROR_UNSPECIFIED;
+
     /** Private constructor to avoid class instantiation. */
     private DisconnectCause() {
         // Do nothing.
     }
+
+    /** Returns descriptive string for the specified disconnect cause. */
+    public static String toString(int cause) {
+        switch (cause) {
+        case NOT_DISCONNECTED:
+            return "NOT_DISCONNECTED";
+        case INCOMING_MISSED:
+            return "INCOMING_MISSED";
+        case NORMAL:
+            return "NORMAL";
+        case LOCAL:
+            return "LOCAL";
+        case BUSY:
+            return "BUSY";
+        case CONGESTION:
+            return "CONGESTION";
+        case INVALID_NUMBER:
+            return "INVALID_NUMBER";
+        case NUMBER_UNREACHABLE:
+            return "NUMBER_UNREACHABLE";
+        case SERVER_UNREACHABLE:
+            return "SERVER_UNREACHABLE";
+        case INVALID_CREDENTIALS:
+            return "INVALID_CREDENTIALS";
+        case OUT_OF_NETWORK:
+            return "OUT_OF_NETWORK";
+        case SERVER_ERROR:
+            return "SERVER_ERROR";
+        case TIMED_OUT:
+            return "TIMED_OUT";
+        case LOST_SIGNAL:
+            return "LOST_SIGNAL";
+        case LIMIT_EXCEEDED:
+            return "LIMIT_EXCEEDED";
+        case INCOMING_REJECTED:
+            return "INCOMING_REJECTED";
+        case POWER_OFF:
+            return "POWER_OFF";
+        case OUT_OF_SERVICE:
+            return "OUT_OF_SERVICE";
+        case ICC_ERROR:
+            return "ICC_ERROR";
+        case CALL_BARRED:
+            return "CALL_BARRED";
+        case FDN_BLOCKED:
+            return "FDN_BLOCKED";
+        case CS_RESTRICTED:
+            return "CS_RESTRICTED";
+        case CS_RESTRICTED_NORMAL:
+            return "CS_RESTRICTED_NORMAL";
+        case CS_RESTRICTED_EMERGENCY:
+            return "CS_RESTRICTED_EMERGENCY";
+        case UNOBTAINABLE_NUMBER:
+            return "UNOBTAINABLE_NUMBER";
+        case CDMA_LOCKED_UNTIL_POWER_CYCLE:
+            return "CDMA_LOCKED_UNTIL_POWER_CYCLE";
+        case CDMA_DROP:
+            return "CDMA_DROP";
+        case CDMA_INTERCEPT:
+            return "CDMA_INTERCEPT";
+        case CDMA_REORDER:
+            return "CDMA_REORDER";
+        case CDMA_SO_REJECT:
+            return "CDMA_SO_REJECT";
+        case CDMA_RETRY_ORDER:
+            return "CDMA_RETRY_ORDER";
+        case CDMA_ACCESS_FAILURE:
+            return "CDMA_ACCESS_FAILURE";
+        case CDMA_PREEMPTED:
+            return "CDMA_PREEMPTED";
+        case CDMA_NOT_EMERGENCY:
+            return "CDMA_NOT_EMERGENCY";
+        case CDMA_ACCESS_BLOCKED:
+            return "CDMA_ACCESS_BLOCKED";
+        case ERROR_UNSPECIFIED:
+            return "ERROR_UNSPECIFIED";
+        default:
+            return "INVALID";
+        }
+    }
 }
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 38bf540..0b1f985 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -1317,9 +1317,9 @@
                         curIsFormatted = false;
                         // Untranslatable strings must only exist in the default [empty] locale
                         if (locale.size() > 0) {
-                            fprintf(stderr, "aapt: warning: string '%s' in %s marked untranslatable but exists"
-                                    " in locale '%s'\n", String8(name).string(),
-                                    bundle->getResourceSourceDirs()[0],
+                            SourcePos(in->getPrintableSource(), block.getLineNumber()).warning(
+                                    "string '%s' marked untranslatable but exists in locale '%s'\n",
+                                    String8(name).string(),
                                     locale.string());
                             // hasErrors = localHasErrors = true;
                         } else {
@@ -1330,7 +1330,10 @@
                             // having no default translation.
                         }
                     } else {
-                        outTable->addLocalization(name, locale);
+                        outTable->addLocalization(
+                                name,
+                                locale,
+                                SourcePos(in->getPrintableSource(), block.getLineNumber()));
                     }
 
                     if (formatted == false16) {
@@ -2570,9 +2573,9 @@
 
 
 void
-ResourceTable::addLocalization(const String16& name, const String8& locale)
+ResourceTable::addLocalization(const String16& name, const String8& locale, const SourcePos& src)
 {
-    mLocalizations[name].insert(locale);
+    mLocalizations[name][locale] = src;
 }
 
 
@@ -2592,21 +2595,22 @@
     const String8 defaultLocale;
 
     // For all strings...
-    for (map<String16, set<String8> >::iterator nameIter = mLocalizations.begin();
+    for (map<String16, map<String8, SourcePos> >::iterator nameIter = mLocalizations.begin();
          nameIter != mLocalizations.end();
          nameIter++) {
-        const set<String8>& configSet = nameIter->second;   // naming convenience
+        const map<String8, SourcePos>& configSrcMap = nameIter->second;
 
         // Look for strings with no default localization
-        if (configSet.count(defaultLocale) == 0) {
-            fprintf(stdout, "aapt: warning: string '%s' has no default translation in %s; found:",
-                    String8(nameIter->first).string(), mBundle->getResourceSourceDirs()[0]);
-            for (set<String8>::const_iterator locales = configSet.begin();
-                 locales != configSet.end();
-                 locales++) {
-                fprintf(stdout, " %s", (*locales).string());
+        if (configSrcMap.count(defaultLocale) == 0) {
+            SourcePos().warning("string '%s' has no default translation.",
+                    String8(nameIter->first).string());
+            if (mBundle->getVerbose()) {
+                for (map<String8, SourcePos>::const_iterator locales = configSrcMap.begin();
+                    locales != configSrcMap.end();
+                    locales++) {
+                    locales->second.printf("locale %s found", locales->first.string());
+                }
             }
-            fprintf(stdout, "\n");
             // !!! TODO: throw an error here in some circumstances
         }
 
@@ -2616,6 +2620,8 @@
             const char* start = allConfigs;
             const char* comma;
             
+            set<String8> missingConfigs;
+            AaptLocaleValue locale;
             do {
                 String8 config;
                 comma = strchr(start, ',');
@@ -2626,27 +2632,38 @@
                     config.setTo(start);
                 }
 
+                if (!locale.initFromFilterString(config)) {
+                    continue;
+                }
+
                 // don't bother with the pseudolocale "zz_ZZ"
                 if (config != "zz_ZZ") {
-                    if (configSet.find(config) == configSet.end()) {
+                    if (configSrcMap.find(config) == configSrcMap.end()) {
                         // okay, no specific localization found.  it's possible that we are
                         // requiring a specific regional localization [e.g. de_DE] but there is an
                         // available string in the generic language localization [e.g. de];
                         // consider that string to have fulfilled the localization requirement.
                         String8 region(config.string(), 2);
-                        if (configSet.find(region) == configSet.end()) {
-                            if (configSet.count(defaultLocale) == 0) {
-                                fprintf(stdout, "aapt: warning: "
-                                        "**** string '%s' has no default or required localization "
-                                        "for '%s' in %s\n",
-                                        String8(nameIter->first).string(),
-                                        config.string(),
-                                        mBundle->getResourceSourceDirs()[0]);
-                            }
+                        if (configSrcMap.find(region) == configSrcMap.end() &&
+                                configSrcMap.count(defaultLocale) == 0) {
+                            missingConfigs.insert(config);
                         }
                     }
                 }
-           } while (comma != NULL);
+            } while (comma != NULL);
+
+            if (!missingConfigs.empty()) {
+                String8 configStr;
+                for (set<String8>::iterator iter = missingConfigs.begin();
+                     iter != missingConfigs.end();
+                     iter++) {
+                    configStr.appendFormat(" %s", iter->string());
+                }
+                SourcePos().warning("string '%s' is missing %u required localizations:%s",
+                        String8(nameIter->first).string(),
+                        (unsigned int)missingConfigs.size(),
+                        configStr.string());
+            }
         }
     }
 
diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
index a3e0666..75005cd 100644
--- a/tools/aapt/ResourceTable.h
+++ b/tools/aapt/ResourceTable.h
@@ -220,7 +220,7 @@
 
     status_t assignResourceIds();
     status_t addSymbols(const sp<AaptSymbols>& outSymbols = NULL);
-    void addLocalization(const String16& name, const String8& locale);
+    void addLocalization(const String16& name, const String8& locale, const SourcePos& src);
     status_t validateLocalizations(void);
 
     status_t flatten(Bundle*, const sp<AaptFile>& dest);
@@ -551,7 +551,7 @@
     Bundle* mBundle;
     
     // key = string resource name, value = set of locales in which that name is defined
-    map<String16, set<String8> > mLocalizations;
+    map<String16, map<String8, SourcePos> > mLocalizations;
 };
 
 #endif
diff --git a/tools/aapt/SourcePos.cpp b/tools/aapt/SourcePos.cpp
index e2a921c..ae25047 100644
--- a/tools/aapt/SourcePos.cpp
+++ b/tools/aapt/SourcePos.cpp
@@ -10,17 +10,20 @@
 // =============================================================================
 struct ErrorPos
 {
+    enum Level {
+        NOTE,
+        WARNING,
+        ERROR
+    };
+
     String8 file;
     int line;
     String8 error;
-    bool fatal;
+    Level level;
 
     ErrorPos();
     ErrorPos(const ErrorPos& that);
-    ErrorPos(const String8& file, int line, const String8& error, bool fatal);
-    ~ErrorPos();
-    bool operator<(const ErrorPos& rhs) const;
-    bool operator==(const ErrorPos& rhs) const;
+    ErrorPos(const String8& file, int line, const String8& error, Level level);
     ErrorPos& operator=(const ErrorPos& rhs);
 
     void print(FILE* to) const;
@@ -29,7 +32,7 @@
 static vector<ErrorPos> g_errors;
 
 ErrorPos::ErrorPos()
-    :line(-1), fatal(false)
+    :line(-1), level(NOTE)
 {
 }
 
@@ -37,61 +40,52 @@
     :file(that.file),
      line(that.line),
      error(that.error),
-     fatal(that.fatal)
+     level(that.level)
 {
 }
 
-ErrorPos::ErrorPos(const String8& f, int l, const String8& e, bool fat)
+ErrorPos::ErrorPos(const String8& f, int l, const String8& e, Level lev)
     :file(f),
      line(l),
      error(e),
-     fatal(fat)
+     level(lev)
 {
 }
 
-ErrorPos::~ErrorPos()
-{
-}
-
-bool
-ErrorPos::operator<(const ErrorPos& rhs) const
-{
-    if (this->file < rhs.file) return true;
-    if (this->file == rhs.file) {
-        if (this->line < rhs.line) return true;
-        if (this->line == rhs.line) {
-            if (this->error < rhs.error) return true;
-        }
-    }
-    return false;
-}
-
-bool
-ErrorPos::operator==(const ErrorPos& rhs) const
-{
-    return this->file == rhs.file
-            && this->line == rhs.line
-            && this->error == rhs.error;
-}
-
 ErrorPos&
 ErrorPos::operator=(const ErrorPos& rhs)
 {
     this->file = rhs.file;
     this->line = rhs.line;
     this->error = rhs.error;
+    this->level = rhs.level;
     return *this;
 }
 
 void
 ErrorPos::print(FILE* to) const
 {
-    const char* type = fatal ? "error:" : "warning:";
+    const char* type = "";
+    switch (level) {
+    case NOTE:
+        type = "note: ";
+        break;
+    case WARNING:
+        type = "warning: ";
+        break;
+    case ERROR:
+        type = "error: ";
+        break;
+    }
     
-    if (this->line >= 0) {
-        fprintf(to, "%s:%d: %s %s\n", this->file.string(), this->line, type, this->error.string());
+    if (!this->file.isEmpty()) {
+        if (this->line >= 0) {
+            fprintf(to, "%s:%d: %s%s\n", this->file.string(), this->line, type, this->error.string());
+        } else {
+            fprintf(to, "%s: %s%s\n", this->file.string(), type, this->error.string());
+        }
     } else {
-        fprintf(to, "%s: %s %s\n", this->file.string(), type, this->error.string());
+        fprintf(to, "%s%s\n", type, this->error.string());
     }
 }
 
@@ -116,40 +110,34 @@
 {
 }
 
-int
+void
 SourcePos::error(const char* fmt, ...) const
 {
-    int retval=0;
-    char buf[1024];
     va_list ap;
     va_start(ap, fmt);
-    retval = vsnprintf(buf, sizeof(buf), fmt, ap);
+    String8 msg = String8::formatV(fmt, ap);
     va_end(ap);
-    char* p = buf + retval - 1;
-    while (p > buf && *p == '\n') {
-        *p = '\0';
-        p--;
-    }
-    g_errors.push_back(ErrorPos(this->file, this->line, String8(buf), true));
-    return retval;
+    g_errors.push_back(ErrorPos(this->file, this->line, msg, ErrorPos::ERROR));
 }
 
-int
+void
 SourcePos::warning(const char* fmt, ...) const
 {
-    int retval=0;
-    char buf[1024];
     va_list ap;
     va_start(ap, fmt);
-    retval = vsnprintf(buf, sizeof(buf), fmt, ap);
+    String8 msg = String8::formatV(fmt, ap);
     va_end(ap);
-    char* p = buf + retval - 1;
-    while (p > buf && *p == '\n') {
-        *p = '\0';
-        p--;
-    }
-    ErrorPos(this->file, this->line, String8(buf), false).print(stderr);
-    return retval;
+    ErrorPos(this->file, this->line, msg, ErrorPos::WARNING).print(stderr);
+}
+
+void
+SourcePos::printf(const char* fmt, ...) const
+{
+    va_list ap;
+    va_start(ap, fmt);
+    String8 msg = String8::formatV(fmt, ap);
+    va_end(ap);
+    ErrorPos(this->file, this->line, msg, ErrorPos::NOTE).print(stderr);
 }
 
 bool
diff --git a/tools/aapt/SourcePos.h b/tools/aapt/SourcePos.h
index 33f72a9..4ce817f 100644
--- a/tools/aapt/SourcePos.h
+++ b/tools/aapt/SourcePos.h
@@ -17,8 +17,9 @@
     SourcePos();
     ~SourcePos();
 
-    int error(const char* fmt, ...) const;
-    int warning(const char* fmt, ...) const;
+    void error(const char* fmt, ...) const;
+    void warning(const char* fmt, ...) const;
+    void printf(const char* fmt, ...) const;
 
     static bool hasErrors();
     static void printErrors(FILE* to);