Merge "Don't prevent notification updates in DOS protection."
diff --git a/Android.mk b/Android.mk
index d9e4455..e2eabed 100644
--- a/Android.mk
+++ b/Android.mk
@@ -406,6 +406,7 @@
 LOCAL_MODULE := framework
 
 LOCAL_DX_FLAGS := --core-library --multi-dex
+LOCAL_JACK_FLAGS := --multi-dex native
 
 LOCAL_RMTYPEDEFS := true
 
@@ -417,6 +418,7 @@
 framework_res_R_stamp := \
 	$(call intermediates-dir-for,APPS,framework-res,,COMMON)/src/R.stamp
 $(full_classes_compiled_jar): $(framework_res_R_stamp)
+$(built_dex_intermediate): $(framework_res_R_stamp)
 
 $(framework_module): | $(dir $(framework_module))framework-res.apk
 
diff --git a/cmds/app_process/Android.mk b/cmds/app_process/Android.mk
index ce6d7b5..171809c 100644
--- a/cmds/app_process/Android.mk
+++ b/cmds/app_process/Android.mk
@@ -52,11 +52,13 @@
 LOCAL_CPPFLAGS := -std=c++11
 
 LOCAL_MODULE := app_process__asan
-LOCAL_MODULE_TAGS := eng
-LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)/asan
-LOCAL_MODULE_STEM := app_process
-LOCAL_ADDRESS_SANITIZER := true
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := app_process32
+LOCAL_MODULE_STEM_64 := app_process64
+
+LOCAL_SANITIZE := address
 LOCAL_CLANG := true
+LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)/asan
 
 LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
 
diff --git a/cmds/input/src/com/android/commands/input/Input.java b/cmds/input/src/com/android/commands/input/Input.java
index 2a7c79b..754d3f5 100644
--- a/cmds/input/src/com/android/commands/input/Input.java
+++ b/cmds/input/src/com/android/commands/input/Input.java
@@ -234,6 +234,18 @@
                 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
     }
 
+    private int getInputDeviceId(int inputSource) {
+        final int DEFAULT_DEVICE_ID = 0;
+        int[] devIds = InputDevice.getDeviceIds();
+        for (int devId : devIds) {
+            InputDevice inputDev = InputDevice.getDevice(devId);
+            if (inputDev.supportsSource(inputSource)) {
+                return devId;
+            }
+        }
+        return DEFAULT_DEVICE_ID;
+    }
+
     /**
      * Builds a MotionEvent and injects it into the event stream.
      *
@@ -249,11 +261,10 @@
         final int DEFAULT_META_STATE = 0;
         final float DEFAULT_PRECISION_X = 1.0f;
         final float DEFAULT_PRECISION_Y = 1.0f;
-        final int DEFAULT_DEVICE_ID = 0;
         final int DEFAULT_EDGE_FLAGS = 0;
         MotionEvent event = MotionEvent.obtain(when, when, action, x, y, pressure, DEFAULT_SIZE,
-                DEFAULT_META_STATE, DEFAULT_PRECISION_X, DEFAULT_PRECISION_Y, DEFAULT_DEVICE_ID,
-                DEFAULT_EDGE_FLAGS);
+                DEFAULT_META_STATE, DEFAULT_PRECISION_X, DEFAULT_PRECISION_Y,
+                getInputDeviceId(inputSource), DEFAULT_EDGE_FLAGS);
         event.setSource(inputSource);
         Log.i(TAG, "injectMotionEvent: " + event);
         InputManager.getInstance().injectInputEvent(event,
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 83c6c2b..7789200 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -55,6 +55,7 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.net.URL;
+import java.util.List;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Enumeration;
@@ -170,6 +171,7 @@
             if (runtimeIsa.equals(secondaryIsa)) {
                 final ApplicationInfo modified = new ApplicationInfo(info);
                 modified.nativeLibraryDir = modified.secondaryNativeLibraryDir;
+                modified.primaryCpuAbi = modified.secondaryCpuAbi;
                 return modified;
             }
         }
@@ -276,8 +278,9 @@
                     }
                 }
 
-                final ArrayList<String> zipPaths = new ArrayList<>();
-                final ArrayList<String> libPaths = new ArrayList<>();
+                final List<String> zipPaths = new ArrayList<>();
+                final List<String> apkPaths = new ArrayList<>();
+                final List<String> libPaths = new ArrayList<>();
 
                 if (mRegisterPackage) {
                     try {
@@ -333,6 +336,8 @@
                     }
                 }
 
+                apkPaths.addAll(zipPaths);
+
                 if (mSharedLibraries != null) {
                     for (String lib : mSharedLibraries) {
                         if (!zipPaths.contains(lib)) {
@@ -350,6 +355,14 @@
                 }
 
                 final String zip = TextUtils.join(File.pathSeparator, zipPaths);
+
+                // Add path to libraries in apk for current abi
+                if (mApplicationInfo.primaryCpuAbi != null) {
+                    for (String apk : apkPaths) {
+                      libPaths.add(apk + "!/lib/" + mApplicationInfo.primaryCpuAbi);
+                    }
+                }
+
                 final String lib = TextUtils.join(File.pathSeparator, libPaths);
 
                 /*
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index dabb1ce..c6f238e 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -99,6 +99,6 @@
     void getActivityEnergyInfoFromController();
     BluetoothActivityEnergyInfo reportActivityInfo();
 
-    // for dumpsys support
-    String dump();
+    // For dumpsys support
+    void dump(in ParcelFileDescriptor fd);
 }
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 4a087da..3b6c9bd 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -916,6 +916,11 @@
         return (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
     }
 
+    /** @hide */
+    public boolean isInternal() {
+        return (flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0;
+    }
+
     /**
      * @hide
      */
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index 391ef22..96f0df8 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -50,6 +50,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -541,7 +542,7 @@
             }
             fis = mPersistentServicesFile.openRead();
             XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(fis, null);
+            parser.setInput(fis, StandardCharsets.UTF_8.name());
             int eventType = parser.getEventType();
             while (eventType != XmlPullParser.START_TAG
                     && eventType != XmlPullParser.END_DOCUMENT) {
@@ -591,7 +592,7 @@
         try {
             fos = mPersistentServicesFile.startWrite();
             XmlSerializer out = new FastXmlSerializer();
-            out.setOutput(fos, "utf-8");
+            out.setOutput(fos, StandardCharsets.UTF_8.name());
             out.startDocument(null, true);
             out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
             out.startTag(null, "services");
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index b5295fb..66c40f7 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -35,6 +35,7 @@
     Bitmap getUserIcon(int userHandle);
     List<UserInfo> getUsers(boolean excludeDying);
     List<UserInfo> getProfiles(int userHandle, boolean enabledOnly);
+    boolean canAddMoreManagedProfiles();
     UserInfo getProfileParent(int userHandle);
     UserInfo getUserInfo(int userHandle);
     boolean isRestricted();
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index d2eaed3..61ead8f 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -634,8 +634,8 @@
             if ((debugFlags & Zygote.DEBUG_ENABLE_JIT) != 0) {
                 argsForZygote.add("--enable-jit");
             }
-            if ((debugFlags & Zygote.DEBUG_GENERATE_CFI) != 0) {
-                argsForZygote.add("--generate-cfi");
+            if ((debugFlags & Zygote.DEBUG_GENERATE_DEBUG_INFO) != 0) {
+                argsForZygote.add("--generate-debug-info");
             }
             if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
                 argsForZygote.add("--enable-assert");
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index b879c83..52b10be 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -71,6 +71,7 @@
     /** Used to communicate with recovery.  See bootable/recovery/recovery.c. */
     private static File RECOVERY_DIR = new File("/cache/recovery");
     private static File COMMAND_FILE = new File(RECOVERY_DIR, "command");
+    private static File UNCRYPT_FILE = new File(RECOVERY_DIR, "uncrypt_file");
     private static File LOG_FILE = new File(RECOVERY_DIR, "log");
     private static String LAST_PREFIX = "last_";
 
@@ -333,8 +334,21 @@
     public static void installPackage(Context context, File packageFile)
         throws IOException {
         String filename = packageFile.getCanonicalPath();
+
+        FileWriter uncryptFile = new FileWriter(UNCRYPT_FILE);
+        try {
+            uncryptFile.write(filename + "\n");
+        } finally {
+            uncryptFile.close();
+        }
         Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");
 
+        // If the package is on the /data partition, write the block map file
+        // into COMMAND_FILE instead.
+        if (filename.startsWith("/data/")) {
+            filename = "@/cache/recovery/block.map";
+        }
+
         final String filenameArg = "--update_package=" + filename;
         final String localeArg = "--locale=" + Locale.getDefault().toString();
         bootCommand(context, filenameArg, localeArg);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index d124a49..b36624d 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -886,6 +886,22 @@
     }
 
     /**
+     * Checks whether it's possible to add more managed profiles. Caller must hold the MANAGE_USERS
+     * permission.
+     *
+     * @return true if more managed profiles can be added, false if limit has been reached.
+     * @hide
+     */
+    public boolean canAddMoreManagedProfiles() {
+        try {
+            return mService.canAddMoreManagedProfiles();
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not check if we can add more managed profiles", re);
+            return false;
+        }
+    }
+
+    /**
      * Returns list of the profiles of userHandle including
      * userHandle itself.
      * Note that this returns both enabled and not enabled profiles. See
diff --git a/core/java/android/security/IKeystoreService.aidl b/core/java/android/security/IKeystoreService.aidl
index 30ea8e7..4a0107d 100644
--- a/core/java/android/security/IKeystoreService.aidl
+++ b/core/java/android/security/IKeystoreService.aidl
@@ -67,7 +67,8 @@
     OperationResult begin(IBinder appToken, String alias, int purpose, boolean pruneable,
         in KeymasterArguments params, in byte[] entropy, out KeymasterArguments operationParams);
     OperationResult update(IBinder token, in KeymasterArguments params, in byte[] input);
-    OperationResult finish(IBinder token, in KeymasterArguments params, in byte[] signature);
+    OperationResult finish(IBinder token, in KeymasterArguments params, in byte[] signature,
+        in byte[] entropy);
     int abort(IBinder handle);
     boolean isOperationAuthorized(IBinder token);
     int addAuthToken(in byte[] authToken);
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index ac98e8a..14ebec7 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -258,7 +258,7 @@
      * Returns a string describing 'time' as a time relative to 'now'.
      * <p>
      * Time spans in the past are formatted like "42 minutes ago".
-     * Time spans in the future are formatted like "in 42 minutes".
+     * Time spans in the future are formatted like "In 42 minutes".
      *
      * @param time the time to describe, in milliseconds
      * @param now the current time in milliseconds
@@ -275,7 +275,7 @@
      * Returns a string describing 'time' as a time relative to 'now'.
      * <p>
      * Time spans in the past are formatted like "42 minutes ago". Time spans in
-     * the future are formatted like "in 42 minutes".
+     * the future are formatted like "In 42 minutes".
      * <p>
      * Can use {@link #FORMAT_ABBREV_RELATIVE} flag to use abbreviated relative
      * times, like "42 mins ago".
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
index 121485a..fe41932 100644
--- a/core/java/android/util/Log.java
+++ b/core/java/android/util/Log.java
@@ -289,7 +289,10 @@
     static int wtf(int logId, String tag, String msg, Throwable tr, boolean localStack,
             boolean system) {
         TerribleFailure what = new TerribleFailure(msg, tr);
-        int bytes = println_native(logId, ASSERT, tag, msg + '\n'
+        // Only mark this as ERROR, do not use ASSERT since that should be
+        // reserved for cases where the system is guaranteed to abort.
+        // The onTerribleFailure call does not always cause a crash.
+        int bytes = println_native(logId, ERROR, tag, msg + '\n'
                 + getStackTraceString(localStack ? what : tr));
         sWtfHandler.onTerribleFailure(tag, what, system);
         return bytes;
diff --git a/core/java/android/widget/ActivityChooserModel.java b/core/java/android/widget/ActivityChooserModel.java
index 51174c3..75c857c 100644
--- a/core/java/android/widget/ActivityChooserModel.java
+++ b/core/java/android/widget/ActivityChooserModel.java
@@ -40,6 +40,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -991,7 +992,7 @@
         }
         try {
             XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(fis, null);
+            parser.setInput(fis, StandardCharsets.UTF_8.name());
 
             int type = XmlPullParser.START_DOCUMENT;
             while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) {
@@ -1074,7 +1075,7 @@
 
             try {
                 serializer.setOutput(fos, null);
-                serializer.startDocument("UTF-8", true);
+                serializer.startDocument(StandardCharsets.UTF_8.name(), true);
                 serializer.startTag(null, TAG_HISTORICAL_RECORDS);
 
                 final int recordCount = historicalRecords.size();
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 86ba780..822117c 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -40,8 +40,8 @@
     public static final int DEBUG_ENABLE_JNI_LOGGING = 1 << 4;
     /** enable the JIT compiler */
     public static final int DEBUG_ENABLE_JIT         = 1 << 5;
-    /** Force generation of CFI code */
-    public static final int DEBUG_GENERATE_CFI       = 1 << 6;
+    /** Force generation of native debugging information. */
+    public static final int DEBUG_GENERATE_DEBUG_INFO = 1 << 6;
 
 
     /** No external storage should be mounted. */
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index f43cc62..8a0e1be 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -322,7 +322,7 @@
 
         /**
          * From --enable-debugger, --enable-checkjni, --enable-assert,
-         * --enable-safemode, --enable-jit, --generate-cfi and --enable-jni-logging.
+         * --enable-safemode, --enable-jit, --generate-debug-info and --enable-jni-logging.
          */
         int debugFlags;
 
@@ -434,8 +434,8 @@
                     debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
                 } else if (arg.equals("--enable-jit")) {
                     debugFlags |= Zygote.DEBUG_ENABLE_JIT;
-                } else if (arg.equals("--generate-cfi")) {
-                    debugFlags |= Zygote.DEBUG_GENERATE_CFI;
+                } else if (arg.equals("--generate-debug-info")) {
+                    debugFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO;
                 } else if (arg.equals("--enable-jni-logging")) {
                     debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
                 } else if (arg.equals("--enable-assert")) {
diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java
index 2bd607c..42caf86 100644
--- a/core/java/com/android/internal/util/XmlUtils.java
+++ b/core/java/com/android/internal/util/XmlUtils.java
@@ -32,6 +32,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.ProtocolException;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -181,7 +182,7 @@
     public static final void writeMapXml(Map val, OutputStream out)
             throws XmlPullParserException, java.io.IOException {
         XmlSerializer serializer = new FastXmlSerializer();
-        serializer.setOutput(out, "utf-8");
+        serializer.setOutput(out, StandardCharsets.UTF_8.name());
         serializer.startDocument(null, true);
         serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
         writeMapXml(val, null, serializer);
@@ -204,7 +205,7 @@
     throws XmlPullParserException, java.io.IOException
     {
         XmlSerializer serializer = Xml.newSerializer();
-        serializer.setOutput(out, "utf-8");
+        serializer.setOutput(out, StandardCharsets.UTF_8.name());
         serializer.startDocument(null, true);
         serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
         writeListXml(val, null, serializer);
@@ -731,7 +732,7 @@
     throws XmlPullParserException, java.io.IOException
     {
         XmlPullParser   parser = Xml.newPullParser();
-        parser.setInput(in, null);
+        parser.setInput(in, StandardCharsets.UTF_8.name());
         return (HashMap<String, ?>) readValueXml(parser, new String[1]);
     }
 
@@ -752,7 +753,7 @@
     throws XmlPullParserException, java.io.IOException
     {
         XmlPullParser   parser = Xml.newPullParser();
-        parser.setInput(in, null);
+        parser.setInput(in, StandardCharsets.UTF_8.name());
         return (ArrayList)readValueXml(parser, new String[1]);
     }
     
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 82fe227..6e8da65 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -874,16 +874,16 @@
     addOption(cpuAbiListBuf);
 
     /*
-     * When running with debug.gencfi, add --include-cfi to the compiler options so that the boot
-     * image, if it is compiled on device, will include CFI info, as well as other compilations
-     * started by the runtime.
+     * When running with debug.generate-debug-info, add --generate-debug-info to
+     * the compiler options so that the boot image, if it is compiled on device,
+     * will include native debugging information.
      */
-    property_get("debug.gencfi", propBuf, "");
+    property_get("debug.generate-debug-info", propBuf, "");
     if (strcmp(propBuf, "true") == 0) {
         addOption("-Xcompiler-option");
-        addOption("--include-cfi");
+        addOption("--generate-debug-info");
         addOption("-Ximage-compiler-option");
-        addOption("--include-cfi");
+        addOption("--generate-debug-info");
     }
 
     initArgs.version = JNI_VERSION_1_4;
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 4f29c50..65eb38c 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -449,15 +449,11 @@
         jniThrowNullPointerException(env, NULL);
         return NULL;
     }
-    const jchar* str = env->GetStringCritical(name, 0);
-    if (str == NULL) {
-        // Whatever, whatever.
-        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+    ScopedUtfChars name8(env, name);
+    if (name8.c_str() == NULL) {
         return NULL;
     }
-    String8 name8(reinterpret_cast<const char16_t*>(str),
-                  env->GetStringLength(name));
-    env->ReleaseStringCritical(name, str);
+
     int flags=0;
     switch (mode&0x30000000) {
         case 0:
@@ -480,7 +476,7 @@
     if (mode&0x00000001) realMode |= S_IROTH;
     if (mode&0x00000002) realMode |= S_IWOTH;
 
-    int fd = open(name8.string(), flags, realMode);
+    int fd = open(name8.c_str(), flags, realMode);
     if (fd < 0) {
         jniThrowException(env, "java/io/FileNotFoundException", strerror(errno));
         return NULL;
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 875ae36..3987170 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -358,6 +358,8 @@
     void add(const sp<JavaDeathRecipient>& recipient);
     void remove(const sp<JavaDeathRecipient>& recipient);
     sp<JavaDeathRecipient> find(jobject recipient);
+
+    Mutex& lock();  // Use with care; specifically for mutual exclusion during binder death
 };
 
 // ----------------------------------------------------------------------------
@@ -392,11 +394,18 @@
                         "*** Uncaught exception returned from death notification!");
             }
 
-            // Demote from strong ref to weak after binderDied() has been delivered,
-            // to allow the DeathRecipient and BinderProxy to be GC'd if no longer needed.
-            mObjectWeak = env->NewWeakGlobalRef(mObject);
-            env->DeleteGlobalRef(mObject);
-            mObject = NULL;
+            // Serialize with our containing DeathRecipientList so that we can't
+            // delete the global ref on mObject while the list is being iterated.
+            sp<DeathRecipientList> list = mList.promote();
+            if (list != NULL) {
+                AutoMutex _l(list->lock());
+
+                // Demote from strong ref to weak after binderDied() has been delivered,
+                // to allow the DeathRecipient and BinderProxy to be GC'd if no longer needed.
+                mObjectWeak = env->NewWeakGlobalRef(mObject);
+                env->DeleteGlobalRef(mObject);
+                mObject = NULL;
+            }
         }
     }
 
@@ -518,6 +527,10 @@
     return NULL;
 }
 
+Mutex& DeathRecipientList::lock() {
+    return mLock;
+}
+
 // ----------------------------------------------------------------------------
 
 namespace android {
diff --git a/core/jni/android_util_Log.cpp b/core/jni/android_util_Log.cpp
index 9a80f1d..2b1067b 100644
--- a/core/jni/android_util_Log.cpp
+++ b/core/jni/android_util_Log.cpp
@@ -41,32 +41,8 @@
 };
 static levels_t levels;
 
-static int toLevel(const char* value)
-{
-    switch (value[0]) {
-        case 'V': return levels.verbose;
-        case 'D': return levels.debug;
-        case 'I': return levels.info;
-        case 'W': return levels.warn;
-        case 'E': return levels.error;
-        case 'A': return levels.assert;
-        case 'S': return -1; // SUPPRESS
-    }
-    return levels.info;
-}
-
 static jboolean isLoggable(const char* tag, jint level) {
-    String8 key;
-    key.append(LOG_NAMESPACE);
-    key.append(tag);
-
-    char buf[PROPERTY_VALUE_MAX];
-    if (property_get(key.string(), buf, "") <= 0) {
-        buf[0] = '\0';
-    }
-
-    int logLevel = toLevel(buf);
-    return logLevel >= 0 && level >= logLevel;
+    return __android_log_is_loggable(level, tag, ANDROID_LOG_INFO);
 }
 
 static jboolean android_util_Log_isLoggable(JNIEnv* env, jobject clazz, jstring tag, jint level)
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 34dc5ad..11b8f0a 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -393,6 +393,16 @@
     <!-- Spoken description for ringer normal option. [CHAR LIMIT=NONE] -->
     <string name="silent_mode_ring">Ringer on</string>
 
+    <!-- Reboot to Recovery Progress Dialog. This is shown before it reboots to recovery. -->
+    <string name="reboot_to_update_title">Android system update</string>
+    <string name="reboot_to_update_prepare">Preparing to update\u2026</string>
+    <string name="reboot_to_update_package">Processing the update package\u2026</string>
+    <string name="reboot_to_update_reboot">Restarting\u2026</string>
+
+    <!-- Reboot to Recovery for factory reset. -->
+    <string name="reboot_to_reset_title">Factory data reset</string>
+    <string name="reboot_to_reset_message">Restarting\u2026</string>
+
     <!-- Shutdown Progress Dialog. This is shown if the user chooses to power off the phone. -->
     <string name="shutdown_progress">Shutting down\u2026</string>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index eec989e..8c1f4e2 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -780,6 +780,12 @@
   <java-symbol type="string" name="mobile_provisioning_url" />
   <java-symbol type="string" name="mobile_redirected_provisioning_url" />
   <java-symbol type="string" name="quick_contacts_not_available" />
+  <java-symbol type="string" name="reboot_to_update_package" />
+  <java-symbol type="string" name="reboot_to_update_prepare" />
+  <java-symbol type="string" name="reboot_to_update_title" />
+  <java-symbol type="string" name="reboot_to_update_reboot" />
+  <java-symbol type="string" name="reboot_to_reset_title" />
+  <java-symbol type="string" name="reboot_to_reset_message" />
   <java-symbol type="string" name="reboot_safemode_confirm" />
   <java-symbol type="string" name="reboot_safemode_title" />
   <java-symbol type="string" name="relationTypeAssistant" />
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
index 7839d26..78e718f 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
@@ -27,18 +27,30 @@
 
 LOCAL_PACKAGE_NAME := MultiDexLegacyAndException
 
+LOCAL_DEX_PREOPT := false
+
 mainDexList:= \
-	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
+    $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
 
 LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
+LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
+    -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
 
-LOCAL_DEX_PREOPT := false
+#################################
+include $(BUILD_SYSTEM)/configure_local_jack.mk
+#################################
+
+ifdef LOCAL_JACK_ENABLED
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
+endif
 
 include $(BUILD_PACKAGE)
 
+ifndef LOCAL_JACK_ENABLED
 $(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
+	$(hide) mkdir -p $(dir $@)
 	$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
 	echo "com/android/multidexlegacyandexception/Test.class" >> $@
 
 $(built_dex_intermediate): $(mainDexList)
-
+endif
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/test.jpp b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/test.jpp
new file mode 100644
index 0000000..0d027ed
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/test.jpp
@@ -0,0 +1,3 @@
+test:
+  @@com.android.jack.annotations.ForceInMainDex
+  class com.android.multidexlegacyandexception.Test
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
index e2ab1a8..7c699b6 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
@@ -27,21 +27,33 @@
 
 LOCAL_PACKAGE_NAME := MultiDexLegacyTestApp
 
+LOCAL_DEX_PREOPT := false
+
 mainDexList:= \
 	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
 
 LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
+LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
+    -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
 
-LOCAL_DEX_PREOPT := false
+#################################
+include $(BUILD_SYSTEM)/configure_local_jack.mk
+#################################
+
+ifdef LOCAL_JACK_ENABLED
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
+endif
 
 include $(BUILD_PACKAGE)
 
+ifndef LOCAL_JACK_ENABLED
 $(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
+	$(hide) mkdir -p $(dir $@)
 	$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
 	echo "com/android/multidexlegacytestapp/Test.class" >> $@
 
 $(built_dex_intermediate): $(mainDexList)
-
+endif
 
 ## The application with a full main dex
 include $(CLEAR_VARS)
@@ -56,17 +68,30 @@
 
 LOCAL_PACKAGE_NAME := MultiDexLegacyTestApp2
 
+LOCAL_DEX_PREOPT := false
+
 mainDexList2:= \
 	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
 
 LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList2)
+LOCAL_JACK_FLAGS := -D jack.dex.output.policy=multidex -D jack.preprocessor=true\
+    -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
 
-LOCAL_DEX_PREOPT := false
+#################################
+include $(BUILD_SYSTEM)/configure_local_jack.mk
+#################################
+
+ifdef LOCAL_JACK_ENABLED
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
+endif
 
 include $(BUILD_PACKAGE)
 
+ifndef LOCAL_JACK_ENABLED
 $(mainDexList2): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
+	$(hide) mkdir -p $(dir $@)
 	$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
 	echo "com/android/multidexlegacytestapp/Test.class" >> $@
 
 $(built_dex_intermediate): $(mainDexList2)
+endif
\ No newline at end of file
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/test.jpp b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/test.jpp
new file mode 100644
index 0000000..a1f5656
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/test.jpp
@@ -0,0 +1,3 @@
+test:
+  @@com.android.jack.annotations.ForceInMainDex
+  class com.android.multidexlegacytestapp.Test
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk
index 329f544..b85c02c 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk
@@ -30,13 +30,16 @@
 	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
 
 LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
+LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.dex.output.multidex.legacy=true
 
 LOCAL_DEX_PREOPT := false
 
 include $(BUILD_PACKAGE)
 
+ifndef LOCAL_JACK_ENABLED
 $(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
+	$(hide) mkdir -p $(dir $@)
 	$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
 
 $(built_dex_intermediate): $(mainDexList)
-
+endif
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
index e79fd71..0f1d9c0 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
@@ -26,18 +26,30 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex
 
+LOCAL_DEX_PREOPT := false
+
 mainDexList:= \
 	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
 
 LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
+LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
+    -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
 
-LOCAL_DEX_PREOPT := false
+#################################
+include $(BUILD_SYSTEM)/configure_local_jack.mk
+#################################
+
+ifdef LOCAL_JACK_ENABLED
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
+endif
 
 include $(BUILD_PACKAGE)
 
+ifndef LOCAL_JACK_ENABLED
 $(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
+	$(hide) mkdir -p $(dir $@)
 	$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
 	echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@
 
 $(built_dex_intermediate): $(mainDexList)
-
+endif
\ No newline at end of file
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/test.jpp b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/test.jpp
new file mode 100644
index 0000000..6d384e3
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/test.jpp
@@ -0,0 +1,3 @@
+test:
+  @@com.android.jack.annotations.ForceInMainDex
+  class com.android.framework.multidexlegacyversionedtestapp.MultiDexUpdateTest
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
index 3742004..67ca483 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
@@ -26,18 +26,30 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex
 
+LOCAL_DEX_PREOPT := false
+
 mainDexList:= \
 	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
 
 LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
+LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
+    -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
 
-LOCAL_DEX_PREOPT := false
+#################################
+include $(BUILD_SYSTEM)/configure_local_jack.mk
+#################################
+
+ifdef LOCAL_JACK_ENABLED
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
+endif
 
 include $(BUILD_PACKAGE)
 
+ifndef LOCAL_JACK_ENABLED
 $(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
+	$(hide) mkdir -p $(dir $@)
 	$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
 	echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@
 
 $(built_dex_intermediate): $(mainDexList)
-
+endif
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/test.jpp b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/test.jpp
new file mode 100644
index 0000000..6d384e3
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/test.jpp
@@ -0,0 +1,3 @@
+test:
+  @@com.android.jack.annotations.ForceInMainDex
+  class com.android.framework.multidexlegacyversionedtestapp.MultiDexUpdateTest
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
index 7f400bc..bf2efb1 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
@@ -29,15 +29,28 @@
 mainDexList:= \
 	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
 
-LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
-
 LOCAL_DEX_PREOPT := false
 
+LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
+LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
+    -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
+
+#################################
+include $(BUILD_SYSTEM)/configure_local_jack.mk
+#################################
+
+ifdef LOCAL_JACK_ENABLED
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
+endif
+
 include $(BUILD_PACKAGE)
 
+ifndef LOCAL_JACK_ENABLED
 $(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
+	$(hide) mkdir -p $(dir $@)
 	$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
 	echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@
 
 $(built_dex_intermediate): $(mainDexList)
+endif
 
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/test.jpp b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/test.jpp
new file mode 100644
index 0000000..6d384e3
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/test.jpp
@@ -0,0 +1,3 @@
+test:
+  @@com.android.jack.annotations.ForceInMainDex
+  class com.android.framework.multidexlegacyversionedtestapp.MultiDexUpdateTest
diff --git a/docs/html/tools/debugging/debugging-log.jd b/docs/html/tools/debugging/debugging-log.jd
index d2baaf26..e222b2a 100644
--- a/docs/html/tools/debugging/debugging-log.jd
+++ b/docs/html/tools/debugging/debugging-log.jd
@@ -284,22 +284,8 @@
   <h2 id="viewingStd">Viewing stdout and stderr</h2>
 
   <p>By default, the Android system sends <code>stdout</code> and <code>stderr</code>
-  (<code>System.out</code> and <code>System.err</code>) output to <code>/dev/null</code>. In
-  processes that run the Dalvik VM, you can have the system write a copy of the output to the log
-  file. In this case, the system writes the messages to the log using the log tags
-  <code>stdout</code> and <code>stderr</code>, both with priority <code>I</code>.</p>
-
-  <p>To route the output in this way, you stop a running emulator/device instance and then use the
-  shell command <code>setprop</code> to enable the redirection of output. Here's how you do it:</p>
-  <pre>
-$ adb shell stop
-$ adb shell setprop log.redirect-stdio true
-$ adb shell start
-</pre>
-
-  <p>The system retains this setting until you terminate the emulator/device instance. To use the
-  setting as a default on the emulator/device instance, you can add an entry to
-  <code>/data/local.prop</code> on the device.</p>
+  output to <code>/dev/null</code>. (The Java <code>System.out</code> and <code>System.err</code>
+  streams go to the log.)
 
   <h2 id="DebuggingWebPages">Debugging Web Apps</h2>
   <p>
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 2558929..c85c3a8 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -474,15 +474,20 @@
         }
     }
 
-    public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature) {
+    public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature,
+            byte[] entropy) {
         try {
-            return mBinder.finish(token, arguments, signature);
+            return mBinder.finish(token, arguments, signature, entropy);
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return null;
         }
     }
 
+    public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature) {
+        return finish(token, arguments, signature, null);
+    }
+
     public int abort(IBinder token) {
         try {
             return mBinder.abort(token);
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index cdf8150..77b66f2 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -25,6 +25,7 @@
 #include "LayerRenderer.h"
 #include "ShadowTessellator.h"
 #include "RenderState.h"
+#include "utils/GLUtils.h"
 
 namespace android {
 
@@ -368,6 +369,12 @@
 
     clearGarbage();
     glFinish();
+
+    // glFinish() need dequeue buffer, and it is not 100% success
+    // It generates gl error sometimes, this error will be there
+    // until glGetError called. Call GLUtils::dumpGLErrors to clean
+    // the error in case it leaks to other functions
+    GLUtils::dumpGLErrors();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/media/tests/MediaDump/src/com/android/mediadump/VideoDumpActivity.java b/media/tests/MediaDump/src/com/android/mediadump/VideoDumpActivity.java
index 46cb64e..b8f5704 100644
--- a/media/tests/MediaDump/src/com/android/mediadump/VideoDumpActivity.java
+++ b/media/tests/MediaDump/src/com/android/mediadump/VideoDumpActivity.java
@@ -19,7 +19,7 @@
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.Context;
-import android.content.DialogInterface;;
+import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.os.Bundle;
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
index 2cc5e04..54d2821 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
@@ -63,6 +63,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -756,7 +757,7 @@
                 out = mStatePersistFile.startWrite();
 
                 XmlSerializer serializer = new FastXmlSerializer();
-                serializer.setOutput(out, "utf-8");
+                serializer.setOutput(out, StandardCharsets.UTF_8.name());
                 serializer.startDocument(null, true);
                 serializer.startTag(null, TAG_SPOOLER);
 
@@ -947,7 +948,7 @@
             }
             try {
                 XmlPullParser parser = Xml.newPullParser();
-                parser.setInput(in, null);
+                parser.setInput(in, StandardCharsets.UTF_8.name());
                 parseState(parser);
             } catch (IllegalStateException ise) {
                 Slog.w(LOG_TAG, "Failed parsing ", ise);
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
index 22a7f86..80c28e0 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
@@ -46,6 +46,7 @@
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.LinkedHashMap;
@@ -562,7 +563,7 @@
                 try {
                     List<PrinterInfo> printers = new ArrayList<>();
                     XmlPullParser parser = Xml.newPullParser();
-                    parser.setInput(in, null);
+                    parser.setInput(in, StandardCharsets.UTF_8.name());
                     parseState(parser, printers);
                     // Take a note which version of the history was read.
                     mLastReadHistoryTimestamp = mStatePersistFile.getBaseFile().lastModified();
@@ -686,7 +687,7 @@
                     out = mStatePersistFile.startWrite();
 
                     XmlSerializer serializer = new FastXmlSerializer();
-                    serializer.setOutput(out, "utf-8");
+                    serializer.setOutput(out, StandardCharsets.UTF_8.name());
                     serializer.startDocument(null, true);
                     serializer.startTag(null, TAG_PRINTERS);
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index fae0643..5f4e4ca 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -33,6 +33,7 @@
 import android.media.AudioManager;
 import android.media.SoundPool;
 import android.os.Bundle;
+import android.os.DeadObjectException;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -380,14 +381,17 @@
                         + ",state=" + simState + ")");
             }
 
-            try {
-                int size = mKeyguardStateCallbacks.size();
-                boolean simPinSecure = mUpdateMonitor.isSimPinSecure();
-                for (int i = 0; i < size; i++) {
+            int size = mKeyguardStateCallbacks.size();
+            boolean simPinSecure = mUpdateMonitor.isSimPinSecure();
+            for (int i = size - 1; i >= 0; i--) {
+                try {
                     mKeyguardStateCallbacks.get(i).onSimSecureStateChanged(simPinSecure);
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "Failed to call onSimSecureStateChanged", e);
+                    if (e instanceof DeadObjectException) {
+                        mKeyguardStateCallbacks.remove(i);
+                    }
                 }
-            } catch (RemoteException e) {
-                Slog.w(TAG, "Failed to call onSimSecureStateChanged", e);
             }
 
             switch (simState) {
@@ -540,6 +544,7 @@
 
         // Assume keyguard is showing (unless it's disabled) until we know for sure...
         setShowingLocked(!shouldWaitForProvisioning() && !mLockPatternUtils.isLockScreenDisabled());
+        updateInputRestrictedLocked();
         mTrustManager.reportKeyguardShowingChanged();
 
         mStatusBarKeyguardViewManager = new StatusBarKeyguardViewManager(mContext,
@@ -929,13 +934,16 @@
         boolean inputRestricted = isInputRestricted();
         if (mInputRestricted != inputRestricted) {
             mInputRestricted = inputRestricted;
-            try {
-                int size = mKeyguardStateCallbacks.size();
-                for (int i = 0; i < size; i++) {
+            int size = mKeyguardStateCallbacks.size();
+            for (int i = size - 1; i >= 0; i--) {
+                try {
                     mKeyguardStateCallbacks.get(i).onInputRestrictedStateChanged(inputRestricted);
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "Failed to call onDeviceProvisioned", e);
+                    if (e instanceof DeadObjectException) {
+                        mKeyguardStateCallbacks.remove(i);
+                    }
                 }
-            } catch (RemoteException e) {
-                Slog.w(TAG, "Failed to call onDeviceProvisioned", e);
             }
         }
     }
@@ -1531,13 +1539,16 @@
     private void setShowingLocked(boolean showing) {
         if (showing != mShowing) {
             mShowing = showing;
-            try {
-                int size = mKeyguardStateCallbacks.size();
-                for (int i = 0; i < size; i++) {
+            int size = mKeyguardStateCallbacks.size();
+            for (int i = size - 1; i >= 0; i--) {
+                try {
                     mKeyguardStateCallbacks.get(i).onShowingStateChanged(showing);
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "Failed to call onShowingStateChanged", e);
+                    if (e instanceof DeadObjectException) {
+                        mKeyguardStateCallbacks.remove(i);
+                    }
                 }
-            } catch (RemoteException e) {
-                Slog.w(TAG, "Failed to call onShowingStateChanged", e);
             }
             updateInputRestrictedLocked();
             mTrustManager.reportKeyguardShowingChanged();
@@ -1550,8 +1561,9 @@
             try {
                 callback.onSimSecureStateChanged(mUpdateMonitor.isSimPinSecure());
                 callback.onShowingStateChanged(mShowing);
+                callback.onInputRestrictedStateChanged(mInputRestricted);
             } catch (RemoteException e) {
-                Slog.w(TAG, "Failed to call onShowingStateChanged or onSimSecureStateChanged", e);
+                Slog.w(TAG, "Failed to call onShowingStateChanged or onSimSecureStateChanged or onInputRestrictedStateChanged", e);
             }
         }
     }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index af5025b..d4c530b 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -472,6 +472,11 @@
     /** The window that is currently dismissing the keyguard. Dismissing the keyguard must only
      * be done once per window. */
     private WindowState mWinDismissingKeyguard;
+    /** When window is currently dismissing the keyguard, dismissing the keyguard must handle
+     * the keygaurd secure state change instantly case, e.g. the use case of inserting a PIN
+     * lock SIM card. This variable is used to record the previous keyguard secure state for
+     * monitoring secure state change on window dismissing keyguard. */
+    private boolean mSecureDismissingKeyguard;
 
     /** The window that is currently showing "over" the keyguard. If there is an app window
      * belonging to another app on top of this the keyguard shows. If there is a fullscreen
@@ -4094,9 +4099,11 @@
                             mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
                         if (DEBUG_LAYOUT) Slog.v(TAG,
                                 "Setting mDismissKeyguard true by win " + win);
-                        mDismissKeyguard = mWinDismissingKeyguard == win ?
+                        mDismissKeyguard = mWinDismissingKeyguard == win
+                                && mSecureDismissingKeyguard == mKeyguardSecure ?
                                 DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
                         mWinDismissingKeyguard = win;
+                        mSecureDismissingKeyguard = mKeyguardSecure;
                         mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure;
                     } else if (mAppsToBeHidden.isEmpty() && showWhenLocked) {
                         if (DEBUG_LAYOUT) Slog.v(TAG,
@@ -4250,6 +4257,7 @@
                 }
             } else {
                 mWinDismissingKeyguard = null;
+                mSecureDismissingKeyguard = false;
                 mKeyguardHidden = false;
                 if (setKeyguardOccludedLw(false)) {
                     changes |= FINISH_LAYOUT_REDO_LAYOUT
diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java
index 4fa2c81..bd8b652 100644
--- a/rs/java/android/renderscript/Allocation.java
+++ b/rs/java/android/renderscript/Allocation.java
@@ -51,6 +51,7 @@
  * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
  * </div>
  **/
+
 public class Allocation extends BaseObj {
     Type mType;
     Bitmap mBitmap;
@@ -455,28 +456,31 @@
      *
      */
     public void syncAll(int srcLocation) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "syncAll");
-        switch (srcLocation) {
-        case USAGE_GRAPHICS_TEXTURE:
-        case USAGE_SCRIPT:
-            if ((mUsage & USAGE_SHARED) != 0) {
-                copyFrom(mBitmap);
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "syncAll");
+            switch (srcLocation) {
+                case USAGE_GRAPHICS_TEXTURE:
+                case USAGE_SCRIPT:
+                    if ((mUsage & USAGE_SHARED) != 0) {
+                        copyFrom(mBitmap);
+                    }
+                    break;
+                case USAGE_GRAPHICS_CONSTANTS:
+                case USAGE_GRAPHICS_VERTEX:
+                    break;
+                case USAGE_SHARED:
+                    if ((mUsage & USAGE_SHARED) != 0) {
+                        copyTo(mBitmap);
+                    }
+                    break;
+                default:
+                    throw new RSIllegalArgumentException("Source must be exactly one usage type.");
             }
-            break;
-        case USAGE_GRAPHICS_CONSTANTS:
-        case USAGE_GRAPHICS_VERTEX:
-            break;
-        case USAGE_SHARED:
-            if ((mUsage & USAGE_SHARED) != 0) {
-                copyTo(mBitmap);
-            }
-            break;
-        default:
-            throw new RSIllegalArgumentException("Source must be exactly one usage type.");
+            mRS.validate();
+            mRS.nAllocationSyncAll(getIDSafe(), srcLocation);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
         }
-        mRS.validate();
-        mRS.nAllocationSyncAll(getIDSafe(), srcLocation);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
     /**
@@ -487,14 +491,17 @@
      *
      */
     public void ioSend() {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "ioSend");
-        if ((mUsage & USAGE_IO_OUTPUT) == 0) {
-            throw new RSIllegalArgumentException(
-                "Can only send buffer if IO_OUTPUT usage specified.");
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "ioSend");
+            if ((mUsage & USAGE_IO_OUTPUT) == 0) {
+                throw new RSIllegalArgumentException(
+                    "Can only send buffer if IO_OUTPUT usage specified.");
+            }
+            mRS.validate();
+            mRS.nAllocationIoSend(getID(mRS));
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
         }
-        mRS.validate();
-        mRS.nAllocationIoSend(getID(mRS));
-        Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
     /**
@@ -503,14 +510,17 @@
      *
      */
     public void ioReceive() {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "ioReceive");
-        if ((mUsage & USAGE_IO_INPUT) == 0) {
-            throw new RSIllegalArgumentException(
-                "Can only receive if IO_INPUT usage specified.");
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "ioReceive");
+            if ((mUsage & USAGE_IO_INPUT) == 0) {
+                throw new RSIllegalArgumentException(
+                    "Can only receive if IO_INPUT usage specified.");
+            }
+            mRS.validate();
+            mRS.nAllocationIoReceive(getID(mRS));
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
         }
-        mRS.validate();
-        mRS.nAllocationIoReceive(getID(mRS));
-        Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
     /**
@@ -519,28 +529,31 @@
      * @param d Source array.
      */
     public void copyFrom(BaseObj[] d) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
-        mRS.validate();
-        validateIsObject();
-        if (d.length != mCurrentCount) {
-            throw new RSIllegalArgumentException("Array size mismatch, allocation sizeX = " +
-                                                 mCurrentCount + ", array length = " + d.length);
-        }
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
+            mRS.validate();
+            validateIsObject();
+            if (d.length != mCurrentCount) {
+                throw new RSIllegalArgumentException("Array size mismatch, allocation sizeX = " +
+                                                      mCurrentCount + ", array length = " + d.length);
+            }
 
-        if (RenderScript.sPointerSize == 8) {
-            long i[] = new long[d.length * 4];
-            for (int ct=0; ct < d.length; ct++) {
-                i[ct * 4] = d[ct].getID(mRS);
+            if (RenderScript.sPointerSize == 8) {
+                long i[] = new long[d.length * 4];
+                for (int ct=0; ct < d.length; ct++) {
+                    i[ct * 4] = d[ct].getID(mRS);
+                }
+                copy1DRangeFromUnchecked(0, mCurrentCount, i);
+            } else {
+                int i[] = new int[d.length];
+                for (int ct=0; ct < d.length; ct++) {
+                    i[ct] = (int) d[ct].getID(mRS);
+                }
+                copy1DRangeFromUnchecked(0, mCurrentCount, i);
             }
-            copy1DRangeFromUnchecked(0, mCurrentCount, i);
-        } else {
-            int i[] = new int[d.length];
-            for (int ct=0; ct < d.length; ct++) {
-                i[ct] = (int)d[ct].getID(mRS);
-            }
-            copy1DRangeFromUnchecked(0, mCurrentCount, i);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
         }
-        Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
     private void validateBitmapFormat(Bitmap b) {
@@ -599,16 +612,19 @@
     }
 
     private void copyFromUnchecked(Object array, Element.DataType dt, int arrayLen) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
-        mRS.validate();
-        if (mCurrentDimZ > 0) {
-            copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, array, dt, arrayLen);
-        } else if (mCurrentDimY > 0) {
-            copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, array, dt, arrayLen);
-        } else {
-            copy1DRangeFromUnchecked(0, mCurrentCount, array, dt, arrayLen);
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
+            mRS.validate();
+            if (mCurrentDimZ > 0) {
+                copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, array, dt, arrayLen);
+            } else if (mCurrentDimY > 0) {
+                copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, array, dt, arrayLen);
+            } else {
+                copy1DRangeFromUnchecked(0, mCurrentCount, array, dt, arrayLen);
+            }
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
         }
-        Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
     /**
@@ -619,10 +635,13 @@
      * @param array The source data array
      */
     public void copyFromUnchecked(Object array) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
-        copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, false),
-                          java.lang.reflect.Array.getLength(array));
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
+            copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, false),
+                              java.lang.reflect.Array.getLength(array));
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
     }
 
     /**
@@ -679,10 +698,13 @@
      * @param array The source data array
      */
     public void copyFrom(Object array) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
-        copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, true),
-                          java.lang.reflect.Array.getLength(array));
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
+            copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, true),
+                              java.lang.reflect.Array.getLength(array));
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
     }
 
     /**
@@ -747,19 +769,22 @@
      * @param b the source bitmap
      */
     public void copyFrom(Bitmap b) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
-        mRS.validate();
-        if (b.getConfig() == null) {
-            Bitmap newBitmap = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888);
-            Canvas c = new Canvas(newBitmap);
-            c.drawBitmap(b, 0, 0, null);
-            copyFrom(newBitmap);
-            return;
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
+            mRS.validate();
+            if (b.getConfig() == null) {
+                Bitmap newBitmap = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888);
+                Canvas c = new Canvas(newBitmap);
+                c.drawBitmap(b, 0, 0, null);
+                copyFrom(newBitmap);
+                return;
+            }
+            validateBitmapSize(b);
+            validateBitmapFormat(b);
+            mRS.nAllocationCopyFromBitmap(getID(mRS), b);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
         }
-        validateBitmapSize(b);
-        validateBitmapFormat(b);
-        mRS.nAllocationCopyFromBitmap(getID(mRS), b);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
     /**
@@ -769,13 +794,16 @@
      * @param a the source allocation
      */
     public void copyFrom(Allocation a) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
-        mRS.validate();
-        if (!mType.equals(a.getType())) {
-            throw new RSIllegalArgumentException("Types of allocations must match.");
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
+            mRS.validate();
+            if (!mType.equals(a.getType())) {
+                throw new RSIllegalArgumentException("Types of allocations must match.");
+            }
+            copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, a, 0, 0);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
         }
-        copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, a, 0, 0);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
     /**
@@ -891,17 +919,20 @@
 
     private void copy1DRangeFromUnchecked(int off, int count, Object array,
                                           Element.DataType dt, int arrayLen) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked");
-        final int dataSize = mType.mElement.getBytesSize() * count;
-        // AutoPadding for Vec3 Element
-        boolean usePadding = false;
-        if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
-            usePadding = true;
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked");
+            final int dataSize = mType.mElement.getBytesSize() * count;
+            // AutoPadding for Vec3 Element
+            boolean usePadding = false;
+            if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
+                usePadding = true;
+            }
+            data1DChecks(off, count, arrayLen * dt.mSize, dataSize, usePadding);
+            mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, array, dataSize, dt,
+                                  mType.mElement.mType.mSize, usePadding);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
         }
-        data1DChecks(off, count, arrayLen * dt.mSize, dataSize, usePadding);
-        mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, array, dataSize, dt,
-                              mType.mElement.mType.mSize, usePadding);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
     /**
@@ -1053,6 +1084,7 @@
                               mSelectedLOD, mSelectedFace.mID,
                               count, 1, data.getID(mRS), dataOff, 0,
                               data.mSelectedLOD, data.mSelectedFace.mID);
+        Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
     private void validate2DRange(int xoff, int yoff, int w, int h) {
@@ -1074,28 +1106,31 @@
 
     void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, Object array,
                                   Element.DataType dt, int arrayLen) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFromUnchecked");
-        mRS.validate();
-        validate2DRange(xoff, yoff, w, h);
-        final int dataSize = mType.mElement.getBytesSize() * w * h;
-        // AutoPadding for Vec3 Element
-        boolean usePadding = false;
-        int sizeBytes = arrayLen * dt.mSize;
-        if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
-            if (dataSize / 4 * 3 > sizeBytes) {
-                throw new RSIllegalArgumentException("Array too small for allocation type.");
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFromUnchecked");
+            mRS.validate();
+            validate2DRange(xoff, yoff, w, h);
+            final int dataSize = mType.mElement.getBytesSize() * w * h;
+            // AutoPadding for Vec3 Element
+            boolean usePadding = false;
+            int sizeBytes = arrayLen * dt.mSize;
+            if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
+                if (dataSize / 4 * 3 > sizeBytes) {
+                    throw new RSIllegalArgumentException("Array too small for allocation type.");
+                }
+                usePadding = true;
+                sizeBytes = dataSize;
+            } else {
+                if (dataSize > sizeBytes) {
+                    throw new RSIllegalArgumentException("Array too small for allocation type.");
+                }
             }
-            usePadding = true;
-            sizeBytes = dataSize;
-        } else {
-            if (dataSize > sizeBytes) {
-                throw new RSIllegalArgumentException("Array too small for allocation type.");
-            }
+            mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h,
+                                  array, sizeBytes, dt,
+                                  mType.mElement.mType.mSize, usePadding);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
         }
-        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h,
-                              array, sizeBytes, dt,
-                              mType.mElement.mType.mSize, usePadding);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
     /**
@@ -1109,11 +1144,14 @@
      * @param array Data to be placed into the Allocation
      */
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, Object array) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
-        copy2DRangeFromUnchecked(xoff, yoff, w, h, array,
-                                 validateObjectIsPrimitiveArray(array, true),
-                                 java.lang.reflect.Array.getLength(array));
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
+            copy2DRangeFromUnchecked(xoff, yoff, w, h, array,
+                                     validateObjectIsPrimitiveArray(array, true),
+                                     java.lang.reflect.Array.getLength(array));
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
     }
 
     /**
@@ -1194,14 +1232,17 @@
      */
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h,
                                 Allocation data, int dataXoff, int dataYoff) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
-        mRS.validate();
-        validate2DRange(xoff, yoff, w, h);
-        mRS.nAllocationData2D(getIDSafe(), xoff, yoff,
-                              mSelectedLOD, mSelectedFace.mID,
-                              w, h, data.getID(mRS), dataXoff, dataYoff,
-                              data.mSelectedLOD, data.mSelectedFace.mID);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
+            mRS.validate();
+            validate2DRange(xoff, yoff, w, h);
+            mRS.nAllocationData2D(getIDSafe(), xoff, yoff,
+                                  mSelectedLOD, mSelectedFace.mID,
+                                  w, h, data.getID(mRS), dataXoff, dataYoff,
+                                  data.mSelectedLOD, data.mSelectedFace.mID);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
     }
 
     /**
@@ -1214,19 +1255,22 @@
      * @param data the Bitmap to be copied
      */
     public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
-        mRS.validate();
-        if (data.getConfig() == null) {
-            Bitmap newBitmap = Bitmap.createBitmap(data.getWidth(), data.getHeight(), Bitmap.Config.ARGB_8888);
-            Canvas c = new Canvas(newBitmap);
-            c.drawBitmap(data, 0, 0, null);
-            copy2DRangeFrom(xoff, yoff, newBitmap);
-            return;
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
+            mRS.validate();
+            if (data.getConfig() == null) {
+                Bitmap newBitmap = Bitmap.createBitmap(data.getWidth(), data.getHeight(), Bitmap.Config.ARGB_8888);
+                Canvas c = new Canvas(newBitmap);
+                c.drawBitmap(data, 0, 0, null);
+                copy2DRangeFrom(xoff, yoff, newBitmap);
+                return;
+            }
+            validateBitmapFormat(data);
+            validate2DRange(xoff, yoff, data.getWidth(), data.getHeight());
+            mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, data);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
         }
-        validateBitmapFormat(data);
-        validate2DRange(xoff, yoff, data.getWidth(), data.getHeight());
-        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, data);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
     private void validate3DRange(int xoff, int yoff, int zoff, int w, int h, int d) {
@@ -1252,28 +1296,31 @@
      */
     private void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d,
                                           Object array, Element.DataType dt, int arrayLen) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeFromUnchecked");
-        mRS.validate();
-        validate3DRange(xoff, yoff, zoff, w, h, d);
-        final int dataSize = mType.mElement.getBytesSize() * w * h * d;
-        // AutoPadding for Vec3 Element
-        boolean usePadding = false;
-        int sizeBytes = arrayLen * dt.mSize;
-        if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
-            if (dataSize / 4 * 3 > sizeBytes) {
-                throw new RSIllegalArgumentException("Array too small for allocation type.");
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeFromUnchecked");
+            mRS.validate();
+            validate3DRange(xoff, yoff, zoff, w, h, d);
+            final int dataSize = mType.mElement.getBytesSize() * w * h * d;
+            // AutoPadding for Vec3 Element
+            boolean usePadding = false;
+            int sizeBytes = arrayLen * dt.mSize;
+            if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
+                if (dataSize / 4 * 3 > sizeBytes) {
+                    throw new RSIllegalArgumentException("Array too small for allocation type.");
+                }
+                usePadding = true;
+                sizeBytes = dataSize;
+            } else {
+                if (dataSize > sizeBytes) {
+                    throw new RSIllegalArgumentException("Array too small for allocation type.");
+                }
             }
-            usePadding = true;
-            sizeBytes = dataSize;
-        } else {
-            if (dataSize > sizeBytes) {
-                throw new RSIllegalArgumentException("Array too small for allocation type.");
-            }
+            mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, w, h, d,
+                                  array, sizeBytes, dt,
+                                  mType.mElement.mType.mSize, usePadding);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
         }
-        mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, w, h, d,
-                              array, sizeBytes, dt,
-                              mType.mElement.mType.mSize, usePadding);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
     /**
@@ -1290,11 +1337,14 @@
      * @param array to be placed into the allocation
      */
     public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, Object array) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeFrom");
-        copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, array,
-                                 validateObjectIsPrimitiveArray(array, true),
-                                 java.lang.reflect.Array.getLength(array));
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeFrom");
+            copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, array,
+                                     validateObjectIsPrimitiveArray(array, true),
+                                     java.lang.reflect.Array.getLength(array));
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
     }
 
     /**
@@ -1330,34 +1380,40 @@
      * @param b The bitmap to be set from the Allocation.
      */
     public void copyTo(Bitmap b) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
-        mRS.validate();
-        validateBitmapFormat(b);
-        validateBitmapSize(b);
-        mRS.nAllocationCopyToBitmap(getID(mRS), b);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
+            mRS.validate();
+            validateBitmapFormat(b);
+            validateBitmapSize(b);
+            mRS.nAllocationCopyToBitmap(getID(mRS), b);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
     }
 
     private void copyTo(Object array, Element.DataType dt, int arrayLen) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
-        mRS.validate();
-        boolean usePadding = false;
-        if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
-            usePadding = true;
-        }
-        if (usePadding) {
-            if (dt.mSize * arrayLen < mSize / 4 * 3) {
-                throw new RSIllegalArgumentException(
-                    "Size of output array cannot be smaller than size of allocation.");
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
+            mRS.validate();
+            boolean usePadding = false;
+            if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
+                usePadding = true;
             }
-        } else {
-            if (dt.mSize * arrayLen < mSize) {
-                throw new RSIllegalArgumentException(
-                    "Size of output array cannot be smaller than size of allocation.");
+            if (usePadding) {
+                if (dt.mSize * arrayLen < mSize / 4 * 3) {
+                    throw new RSIllegalArgumentException(
+                        "Size of output array cannot be smaller than size of allocation.");
+                }
+            } else {
+                if (dt.mSize * arrayLen < mSize) {
+                    throw new RSIllegalArgumentException(
+                        "Size of output array cannot be smaller than size of allocation.");
+                }
             }
+            mRS.nAllocationRead(getID(mRS), array, dt, mType.mElement.mType.mSize, usePadding);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
         }
-        mRS.nAllocationRead(getID(mRS), array, dt, mType.mElement.mType.mSize, usePadding);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
     /**
@@ -1448,7 +1504,7 @@
         }
 
         final byte[] data = fp.getData();
-        int data_length = fp.getPos();
+        int data_length = data.length;
         int eSize = mType.mElement.mElements[component_number].getBytesSize();
         eSize *= mType.mElement.mArraySizes[component_number];
 
@@ -1494,17 +1550,20 @@
 
     private void copy1DRangeToUnchecked(int off, int count, Object array,
                                         Element.DataType dt, int arrayLen) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeToUnchecked");
-        final int dataSize = mType.mElement.getBytesSize() * count;
-        // AutoPadding for Vec3 Element
-        boolean usePadding = false;
-        if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
-            usePadding = true;
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeToUnchecked");
+            final int dataSize = mType.mElement.getBytesSize() * count;
+            // AutoPadding for Vec3 Element
+            boolean usePadding = false;
+            if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
+                usePadding = true;
+            }
+            data1DChecks(off, count, arrayLen * dt.mSize, dataSize, usePadding);
+            mRS.nAllocationRead1D(getIDSafe(), off, mSelectedLOD, count, array, dataSize, dt,
+                                  mType.mElement.mType.mSize, usePadding);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
         }
-        data1DChecks(off, count, arrayLen * dt.mSize, dataSize, usePadding);
-        mRS.nAllocationRead1D(getIDSafe(), off, mSelectedLOD, count, array, dataSize, dt,
-                              mType.mElement.mType.mSize, usePadding);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
     /**
@@ -1654,27 +1713,30 @@
 
     void copy2DRangeToUnchecked(int xoff, int yoff, int w, int h, Object array,
                                 Element.DataType dt, int arrayLen) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeToUnchecked");
-        mRS.validate();
-        validate2DRange(xoff, yoff, w, h);
-        final int dataSize = mType.mElement.getBytesSize() * w * h;
-        // AutoPadding for Vec3 Element
-        boolean usePadding = false;
-        int sizeBytes = arrayLen * dt.mSize;
-        if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
-            if (dataSize / 4 * 3 > sizeBytes) {
-                throw new RSIllegalArgumentException("Array too small for allocation type.");
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeToUnchecked");
+            mRS.validate();
+            validate2DRange(xoff, yoff, w, h);
+            final int dataSize = mType.mElement.getBytesSize() * w * h;
+            // AutoPadding for Vec3 Element
+            boolean usePadding = false;
+            int sizeBytes = arrayLen * dt.mSize;
+            if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
+                if (dataSize / 4 * 3 > sizeBytes) {
+                    throw new RSIllegalArgumentException("Array too small for allocation type.");
+                }
+                usePadding = true;
+                sizeBytes = dataSize;
+            } else {
+                if (dataSize > sizeBytes) {
+                    throw new RSIllegalArgumentException("Array too small for allocation type.");
+                }
             }
-            usePadding = true;
-            sizeBytes = dataSize;
-        } else {
-            if (dataSize > sizeBytes) {
-                throw new RSIllegalArgumentException("Array too small for allocation type.");
-            }
+            mRS.nAllocationRead2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h,
+                                  array, sizeBytes, dt, mType.mElement.mType.mSize, usePadding);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
         }
-        mRS.nAllocationRead2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h,
-                              array, sizeBytes, dt, mType.mElement.mType.mSize, usePadding);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
     /**
@@ -1764,27 +1826,30 @@
      */
     private void copy3DRangeToUnchecked(int xoff, int yoff, int zoff, int w, int h, int d,
                                         Object array, Element.DataType dt, int arrayLen) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeToUnchecked");
-        mRS.validate();
-        validate3DRange(xoff, yoff, zoff, w, h, d);
-        final int dataSize = mType.mElement.getBytesSize() * w * h * d;
-        // AutoPadding for Vec3 Element
-        boolean usePadding = false;
-        int sizeBytes = arrayLen * dt.mSize;
-        if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
-            if (dataSize / 4 * 3 > sizeBytes) {
-                throw new RSIllegalArgumentException("Array too small for allocation type.");
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeToUnchecked");
+            mRS.validate();
+            validate3DRange(xoff, yoff, zoff, w, h, d);
+            final int dataSize = mType.mElement.getBytesSize() * w * h * d;
+            // AutoPadding for Vec3 Element
+            boolean usePadding = false;
+            int sizeBytes = arrayLen * dt.mSize;
+            if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
+                if (dataSize / 4 * 3 > sizeBytes) {
+                    throw new RSIllegalArgumentException("Array too small for allocation type.");
+                }
+                usePadding = true;
+                sizeBytes = dataSize;
+            } else {
+                if (dataSize > sizeBytes) {
+                    throw new RSIllegalArgumentException("Array too small for allocation type.");
+                }
             }
-            usePadding = true;
-            sizeBytes = dataSize;
-        } else {
-            if (dataSize > sizeBytes) {
-                throw new RSIllegalArgumentException("Array too small for allocation type.");
-            }
+            mRS.nAllocationRead3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, w, h, d,
+                                  array, sizeBytes, dt, mType.mElement.mType.mSize, usePadding);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
         }
-        mRS.nAllocationRead3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, w, h, d,
-                              array, sizeBytes, dt, mType.mElement.mType.mSize, usePadding);
-        Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
     /**
@@ -1823,17 +1888,20 @@
      *              utilized
      */
     static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips, int usage) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "createTyped");
-        rs.validate();
-        if (type.getID(rs) == 0) {
-            throw new RSInvalidStateException("Bad Type");
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "createTyped");
+            rs.validate();
+            if (type.getID(rs) == 0) {
+                throw new RSInvalidStateException("Bad Type");
+            }
+            long id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
+            if (id == 0) {
+                throw new RSRuntimeException("Allocation creation failed.");
+            }
+            return new Allocation(id, rs, type, usage);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
         }
-        long id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
-        if (id == 0) {
-            throw new RSRuntimeException("Allocation creation failed.");
-        }
-        Trace.traceEnd(RenderScript.TRACE_TAG);
-        return new Allocation(id, rs, type, usage);
     }
 
     /**
@@ -1877,18 +1945,21 @@
      */
     static public Allocation createSized(RenderScript rs, Element e,
                                          int count, int usage) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "createSized");
-        rs.validate();
-        Type.Builder b = new Type.Builder(rs, e);
-        b.setX(count);
-        Type t = b.create();
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "createSized");
+            rs.validate();
+            Type.Builder b = new Type.Builder(rs, e);
+            b.setX(count);
+            Type t = b.create();
 
-        long id = rs.nAllocationCreateTyped(t.getID(rs), MipmapControl.MIPMAP_NONE.mID, usage, 0);
-        if (id == 0) {
-            throw new RSRuntimeException("Allocation creation failed.");
+            long id = rs.nAllocationCreateTyped(t.getID(rs), MipmapControl.MIPMAP_NONE.mID, usage, 0);
+            if (id == 0) {
+                throw new RSRuntimeException("Allocation creation failed.");
+            }
+            return new Allocation(id, rs, t, usage);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
         }
-        Trace.traceEnd(RenderScript.TRACE_TAG);
-        return new Allocation(id, rs, t, usage);
     }
 
     /**
@@ -1947,44 +2018,47 @@
     static public Allocation createFromBitmap(RenderScript rs, Bitmap b,
                                               MipmapControl mips,
                                               int usage) {
-        Trace.traceBegin(RenderScript.TRACE_TAG, "createFromBitmap");
-        rs.validate();
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "createFromBitmap");
+            rs.validate();
 
-        // WAR undocumented color formats
-        if (b.getConfig() == null) {
-            if ((usage & USAGE_SHARED) != 0) {
-                throw new RSIllegalArgumentException("USAGE_SHARED cannot be used with a Bitmap that has a null config.");
+            // WAR undocumented color formats
+            if (b.getConfig() == null) {
+                if ((usage & USAGE_SHARED) != 0) {
+                    throw new RSIllegalArgumentException("USAGE_SHARED cannot be used with a Bitmap that has a null config.");
+                }
+                Bitmap newBitmap = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888);
+                Canvas c = new Canvas(newBitmap);
+                c.drawBitmap(b, 0, 0, null);
+                return createFromBitmap(rs, newBitmap, mips, usage);
             }
-            Bitmap newBitmap = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888);
-            Canvas c = new Canvas(newBitmap);
-            c.drawBitmap(b, 0, 0, null);
-            return createFromBitmap(rs, newBitmap, mips, usage);
-        }
 
-        Type t = typeFromBitmap(rs, b, mips);
+            Type t = typeFromBitmap(rs, b, mips);
 
-        // enable optimized bitmap path only with no mipmap and script-only usage
-        if (mips == MipmapControl.MIPMAP_NONE &&
-            t.getElement().isCompatible(Element.RGBA_8888(rs)) &&
-            usage == (USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE)) {
-            long id = rs.nAllocationCreateBitmapBackedAllocation(t.getID(rs), mips.mID, b, usage);
+            // enable optimized bitmap path only with no mipmap and script-only usage
+            if (mips == MipmapControl.MIPMAP_NONE &&
+                 t.getElement().isCompatible(Element.RGBA_8888(rs)) &&
+                 usage == (USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE)) {
+                long id = rs.nAllocationCreateBitmapBackedAllocation(t.getID(rs), mips.mID, b, usage);
+                if (id == 0) {
+                    throw new RSRuntimeException("Load failed.");
+                }
+
+                // keep a reference to the Bitmap around to prevent GC
+                Allocation alloc = new Allocation(id, rs, t, usage);
+                alloc.setBitmap(b);
+                return alloc;
+            }
+
+
+            long id = rs.nAllocationCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
             if (id == 0) {
                 throw new RSRuntimeException("Load failed.");
             }
-
-            // keep a reference to the Bitmap around to prevent GC
-            Allocation alloc = new Allocation(id, rs, t, usage);
-            alloc.setBitmap(b);
-            return alloc;
+            return new Allocation(id, rs, t, usage);
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
         }
-
-
-        long id = rs.nAllocationCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
-        if (id == 0) {
-            throw new RSRuntimeException("Load failed.");
-        }
-        Trace.traceEnd(RenderScript.TRACE_TAG);
-        return new Allocation(id, rs, t, usage);
     }
 
     /**
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 24bc2c1..0505a4b 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -89,6 +89,13 @@
     */
     public static final int CREATE_FLAG_LOW_POWER = 0x0004;
 
+    /**
+     * @hide
+     * Context creation flag which instructs the implementation to wait for
+     * a debugger to be attached before continuing execution.
+    */
+    public static final int CREATE_FLAG_WAIT_FOR_ATTACH = 0x0008;
+
     /*
      * Detect the bitness of the VM to allow FieldPacker to do the right thing.
      */
@@ -1343,7 +1350,7 @@
             return null;
         }
 
-        if ((flags & ~(CREATE_FLAG_LOW_LATENCY | CREATE_FLAG_LOW_POWER)) != 0) {
+        if ((flags & ~(CREATE_FLAG_LOW_LATENCY | CREATE_FLAG_LOW_POWER | CREATE_FLAG_WAIT_FOR_ATTACH)) != 0) {
             throw new RSIllegalArgumentException("Invalid flags passed.");
         }
 
diff --git a/rs/java/android/renderscript/ScriptGroup.java b/rs/java/android/renderscript/ScriptGroup.java
index be8b0fd..5a0897d 100644
--- a/rs/java/android/renderscript/ScriptGroup.java
+++ b/rs/java/android/renderscript/ScriptGroup.java
@@ -131,28 +131,16 @@
 
             int i;
             for (i = 0; i < args.length; i++) {
-                Object obj = args[i];
                 fieldIDs[i] = 0;
-                if (obj instanceof Input) {
-                    Input unbound = (Input)obj;
-                    unbound.addReference(this, i);
-                } else {
-                    retrieveValueAndDependenceInfo(rs, i, args[i], values, sizes,
-                                                   depClosures, depFieldIDs);
-                }
+                retrieveValueAndDependenceInfo(rs, i, null, args[i],
+                                               values, sizes, depClosures, depFieldIDs);
             }
-
             for (Map.Entry<Script.FieldID, Object> entry : globals.entrySet()) {
                 Object obj = entry.getValue();
                 Script.FieldID fieldID = entry.getKey();
                 fieldIDs[i] = fieldID.getID(rs);
-                if (obj instanceof Input) {
-                    Input unbound = (Input)obj;
-                    unbound.addReference(this, fieldID);
-                } else {
-                    retrieveValueAndDependenceInfo(rs, i, obj, values,
-                                                   sizes, depClosures, depFieldIDs);
-                }
+                retrieveValueAndDependenceInfo(rs, i, fieldID, obj,
+                                               values, sizes, depClosures, depFieldIDs);
                 i++;
             }
 
@@ -184,13 +172,8 @@
                 Object obj = entry.getValue();
                 Script.FieldID fieldID = entry.getKey();
                 fieldIDs[i] = fieldID.getID(rs);
-                if (obj instanceof Input) {
-                    Input unbound = (Input)obj;
-                    unbound.addReference(this, fieldID);
-                } else {
-                    retrieveValueAndDependenceInfo(rs, i, obj, values,
-                                                   sizes, depClosures, depFieldIDs);
-                }
+                retrieveValueAndDependenceInfo(rs, i, fieldID, obj, values,
+                                               sizes, depClosures, depFieldIDs);
                 i++;
             }
 
@@ -200,9 +183,8 @@
             setID(id);
         }
 
-        private static
-                void retrieveValueAndDependenceInfo(RenderScript rs,
-                                                    int index, Object obj,
+        private void retrieveValueAndDependenceInfo(RenderScript rs,
+                                                    int index, Script.FieldID fid, Object obj,
                                                     long[] values, int[] sizes,
                                                     long[] depClosures,
                                                     long[] depFieldIDs) {
@@ -213,20 +195,25 @@
                 depClosures[index] = f.getClosure().getID(rs);
                 Script.FieldID fieldID = f.getFieldID();
                 depFieldIDs[index] = fieldID != null ? fieldID.getID(rs) : 0;
-                if (obj == null) {
-                    // Value is originally created by the owner closure
-                    values[index] = 0;
-                    sizes[index] = 0;
-                    return;
-                }
             } else {
                 depClosures[index] = 0;
                 depFieldIDs[index] = 0;
             }
 
-            ValueAndSize vs = new ValueAndSize(rs, obj);
-            values[index] = vs.value;
-            sizes[index] = vs.size;
+            if (obj instanceof Input) {
+                Input unbound = (Input)obj;
+                if (index < mArgs.length) {
+                    unbound.addReference(this, index);
+                } else {
+                    unbound.addReference(this, fid);
+                }
+                values[index] = 0;
+                sizes[index] = 0;
+            } else {
+                ValueAndSize vs = new ValueAndSize(rs, obj);
+                values[index] = vs.value;
+                sizes[index] = vs.size;
+            }
         }
 
         /**
@@ -258,7 +245,11 @@
                 // without an associated value (reference). So this is not working for
                 // cross-module (cross-script) linking in this case where a field not
                 // explicitly bound.
-                f = new Future(this, field, mBindings.get(field));
+                Object obj = mBindings.get(field);
+                if (obj instanceof Future) {
+                    obj = ((Future)obj).getValue();
+                }
+                f = new Future(this, field, obj);
                 mGlobalFuture.put(field, f);
             }
 
@@ -266,12 +257,18 @@
         }
 
         void setArg(int index, Object obj) {
+            if (obj instanceof Future) {
+                obj = ((Future)obj).getValue();
+            }
             mArgs[index] = obj;
             ValueAndSize vs = new ValueAndSize(mRS, obj);
             mRS.nClosureSetArg(getID(mRS), index, vs.value, vs.size);
         }
 
         void setGlobal(Script.FieldID fieldID, Object obj) {
+            if (obj instanceof Future) {
+                obj = ((Future)obj).getValue();
+            }
             mBindings.put(fieldID, obj);
             ValueAndSize vs = new ValueAndSize(mRS, obj);
             mRS.nClosureSetGlobal(getID(mRS), fieldID.getID(mRS), vs.value, vs.size);
@@ -344,6 +341,7 @@
         // -1 means unset. Legal values are 0 .. n-1, where n is the number of
         // arguments for the referencing closure.
         List<Pair<Closure, Integer>> mArgIndex;
+        Object mValue;
 
         Input() {
             mFieldID = new ArrayList<Pair<Closure, Script.FieldID>>();
@@ -359,6 +357,7 @@
         }
 
         void set(Object value) {
+            mValue = value;
             for (Pair<Closure, Integer> p : mArgIndex) {
                 Closure closure = p.first;
                 int index = p.second.intValue();
@@ -370,6 +369,8 @@
                 closure.setGlobal(fieldID, value);
             }
         }
+
+        Object get() { return mValue; }
     }
 
     private String mName;
@@ -432,7 +433,11 @@
         Object[] outputObjs = new Object[mOutputs2.length];
         int i = 0;
         for (Future f : mOutputs2) {
-            outputObjs[i++] = f.getValue();
+            Object output = f.getValue();
+            if (output instanceof Input) {
+                output = ((Input)output).get();
+            }
+            outputObjs[i++] = output;
         }
         return outputObjs;
     }
@@ -590,7 +595,8 @@
                 Node n = mNodes.get(ct);
                 if (n.mInputs.size() == 0) {
                     if (n.mOutputs.size() == 0 && mNodes.size() > 1) {
-                        throw new RSInvalidStateException("Groups cannot contain unconnected scripts");
+                        String msg = "Groups cannot contain unconnected scripts";
+                        throw new RSInvalidStateException(msg);
                     }
                     validateDAGRecurse(n, ct+1);
                 }
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 3665851..ec835b2 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -1462,7 +1462,7 @@
     rsAllocationElementRead((RsContext)con, (RsAllocation)alloc,
                             xoff, yoff, zoff,
                             lod, ptr, sizeBytes, compIdx);
-    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
+    _env->ReleaseByteArrayElements(data, ptr, 0);
 }
 
 // Copies from the Allocation pointed to by _alloc into the Java object data.
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 7623514..ee2d5ff 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -94,6 +94,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -2400,7 +2401,7 @@
 
         try {
             XmlSerializer out = new FastXmlSerializer();
-            out.setOutput(stream, "utf-8");
+            out.setOutput(stream, StandardCharsets.UTF_8.name());
             out.startDocument(null, true);
             out.startTag(null, "gs");
             out.attribute(null, "version", String.valueOf(CURRENT_VERSION));
@@ -2463,7 +2464,7 @@
         int version = -1;
         try {
             XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(stream, null);
+            parser.setInput(stream, StandardCharsets.UTF_8.name());
 
             int legacyProviderIndex = -1;
             int legacyHostIndex = -1;
@@ -3525,7 +3526,7 @@
 
                 try {
                     XmlSerializer out = new FastXmlSerializer();
-                    out.setOutput(stream, "utf-8");
+                    out.setOutput(stream, StandardCharsets.UTF_8.name());
                     out.startDocument(null, true);
                     out.startTag(null, "ws");      // widget state
                     out.attribute(null, "version", String.valueOf(WIDGET_STATE_VERSION));
@@ -3617,7 +3618,7 @@
                 ArrayList<Host> restoredHosts = new ArrayList<>();
 
                 XmlPullParser parser = Xml.newPullParser();
-                parser.setInput(stream, null);
+                parser.setInput(stream, StandardCharsets.UTF_8.name());
 
                 synchronized (mLock) {
                     int type;
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 7d156df..fa906f7 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -369,10 +369,10 @@
         public int compare(Batch b1, Batch b2) {
             long when1 = b1.start;
             long when2 = b2.start;
-            if (when1 - when2 > 0) {
+            if (when1 > when2) {
                 return 1;
             }
-            if (when1 - when2 < 0) {
+            if (when1 < when2) {
                 return -1;
             }
             return 0;
@@ -1480,12 +1480,12 @@
      */
     public static class IncreasingTimeOrder implements Comparator<Alarm> {
         public int compare(Alarm a1, Alarm a2) {
-            long when1 = a1.when;
-            long when2 = a2.when;
-            if (when1 - when2 > 0) {
+            long when1 = a1.whenElapsed;
+            long when2 = a2.whenElapsed;
+            if (when1 > when2) {
                 return 1;
             }
-            if (when1 - when2 < 0) {
+            if (when1 < when2) {
                 return -1;
             }
             return 0;
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 17b4939..9fa30a3 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -23,6 +23,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -910,7 +911,7 @@
                 boolean success = false;
                 try {
                     XmlPullParser parser = Xml.newPullParser();
-                    parser.setInput(stream, null);
+                    parser.setInput(stream, StandardCharsets.UTF_8.name());
                     int type;
                     while ((type = parser.next()) != XmlPullParser.START_TAG
                             && type != XmlPullParser.END_DOCUMENT) {
@@ -1070,7 +1071,7 @@
 
             try {
                 XmlSerializer out = new FastXmlSerializer();
-                out.setOutput(stream, "utf-8");
+                out.setOutput(stream, StandardCharsets.UTF_8.name());
                 out.startDocument(null, true);
                 out.startTag(null, "app-ops");
 
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 32a6a2f..7aa8e11 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -41,6 +41,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
@@ -51,6 +52,7 @@
 import android.util.Log;
 
 import java.io.FileDescriptor;
+import java.io.IOException;
 import java.io.PrintWriter;
 
 import java.util.HashMap;
@@ -1523,17 +1525,32 @@
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
 
-        writer.println("enabled: " + mEnable);
-        writer.println("state: " + mState);
-        writer.println("address: " + mAddress);
-        writer.println("name: " + mName);
+        writer.println("Bluetooth Status");
+        writer.println("  enabled: " + mEnable);
+        writer.println("  state: " + mState);
+        writer.println("  address: " + mAddress);
+        writer.println("  name: " + mName + "\n");
+        writer.flush();
+
         if (mBluetooth == null) {
             writer.println("Bluetooth Service not connected");
         } else {
+            ParcelFileDescriptor pfd = null;
             try {
-                writer.println(mBluetooth.dump());
+                pfd = ParcelFileDescriptor.dup(fd);
+                mBluetooth.dump(pfd);
             } catch (RemoteException re) {
                 writer.println("RemoteException while calling Bluetooth Service");
+            } catch (IOException ioe) {
+                writer.println("IOException attempting to dup() fd");
+            } finally {
+                if (pfd != null) {
+                    try {
+                        pfd.close();
+                    } catch (IOException ioe) {
+                        writer.println("IOException attempting to close() fd");
+                    }
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 4d0868a..c74983e 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -122,6 +122,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -3398,7 +3399,7 @@
             try {
                 fos = subtypesFile.startWrite();
                 final XmlSerializer out = new FastXmlSerializer();
-                out.setOutput(fos, "utf-8");
+                out.setOutput(fos, StandardCharsets.UTF_8.name());
                 out.startDocument(null, true);
                 out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
                 out.startTag(null, NODE_SUBTYPES);
@@ -3444,7 +3445,7 @@
             try {
                 fis = subtypesFile.openRead();
                 final XmlPullParser parser = Xml.newPullParser();
-                parser.setInput(fis, null);
+                parser.setInput(fis, StandardCharsets.UTF_8.name());
                 int type = parser.getEventType();
                 // Skip parsing until START_TAG
                 while ((type = parser.next()) != XmlPullParser.START_TAG
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 4e7aa77..24ae766 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -509,7 +509,7 @@
             // r.record is null if findServiceLocked() failed the caller permission check
             if (r.record == null) {
                 throw new SecurityException(
-                        "Permission Denial: Accessing service " + r.record.name
+                        "Permission Denial: Accessing service"
                         + " from pid=" + Binder.getCallingPid()
                         + ", uid=" + Binder.getCallingUid()
                         + " requires " + r.permission);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 01858a4..da2b91e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -222,6 +222,7 @@
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.lang.ref.WeakReference;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -3016,9 +3017,9 @@
                     debugFlags |= Zygote.DEBUG_ENABLE_JIT;
                 }
             }
-            String genCFIDebugProperty = SystemProperties.get("debug.gencfi");
-            if ("true".equals(genCFIDebugProperty)) {
-                debugFlags |= Zygote.DEBUG_GENERATE_CFI;
+            String genDebugInfoProperty = SystemProperties.get("debug.generate-debug-info");
+            if ("true".equals(genDebugInfoProperty)) {
+                debugFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO;
             }
             if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
                 debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
@@ -7799,7 +7800,7 @@
             fos = mGrantFile.startWrite();
 
             XmlSerializer out = new FastXmlSerializer();
-            out.setOutput(fos, "utf-8");
+            out.setOutput(fos, StandardCharsets.UTF_8.name());
             out.startDocument(null, true);
             out.startTag(null, TAG_URI_GRANTS);
             for (UriPermission.Snapshot perm : persist) {
@@ -7834,7 +7835,7 @@
         try {
             fis = mGrantFile.openRead();
             final XmlPullParser in = Xml.newPullParser();
-            in.setInput(fis, null);
+            in.setInput(fis, StandardCharsets.UTF_8.name());
 
             int type;
             while ((type = in.next()) != END_DOCUMENT) {
diff --git a/services/core/java/com/android/server/am/CompatModePackages.java b/services/core/java/com/android/server/am/CompatModePackages.java
index ec500c2..2ba2bbd 100644
--- a/services/core/java/com/android/server/am/CompatModePackages.java
+++ b/services/core/java/com/android/server/am/CompatModePackages.java
@@ -19,6 +19,7 @@
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
@@ -84,7 +85,7 @@
         try {
             fis = mFile.openRead();
             XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(fis, null);
+            parser.setInput(fis, StandardCharsets.UTF_8.name());
             int eventType = parser.getEventType();
             while (eventType != XmlPullParser.START_TAG &&
                     eventType != XmlPullParser.END_DOCUMENT) {
@@ -360,7 +361,7 @@
         try {
             fos = mFile.startWrite();
             XmlSerializer out = new FastXmlSerializer();
-            out.setOutput(fos, "utf-8");
+            out.setOutput(fos, StandardCharsets.UTF_8.name());
             out.startDocument(null, true);
             out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
             out.startTag(null, "compat-packages");
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index 0d5f240..eeeb1fd 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -57,6 +57,7 @@
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.HashMap;
@@ -1811,7 +1812,7 @@
                 Log.v(TAG_FILE, "Reading " + mAccountInfoFile.getBaseFile());
             }
             XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(fis, null);
+            parser.setInput(fis, StandardCharsets.UTF_8.name());
             int eventType = parser.getEventType();
             while (eventType != XmlPullParser.START_TAG &&
                     eventType != XmlPullParser.END_DOCUMENT) {
@@ -2150,7 +2151,7 @@
         try {
             fos = mAccountInfoFile.startWrite();
             XmlSerializer out = new FastXmlSerializer();
-            out.setOutput(fos, "utf-8");
+            out.setOutput(fos, StandardCharsets.UTF_8.name());
             out.startDocument(null, true);
             out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
 
@@ -2442,7 +2443,7 @@
             }
             XmlPullParser parser;
             parser = Xml.newPullParser();
-            parser.setInput(fis, null);
+            parser.setInput(fis, StandardCharsets.UTF_8.name());
 
             int eventType = parser.getEventType();
             while (eventType != XmlPullParser.START_TAG &&
@@ -2578,7 +2579,7 @@
             }
             fos = mPendingFile.startWrite();
             XmlSerializer out = new FastXmlSerializer();
-            out.setOutput(fos, "utf-8");
+            out.setOutput(fos, StandardCharsets.UTF_8.name());
 
             for (int i = 0; i < N; i++) {
                 PendingOperation pop = mPendingOperations.get(i);
@@ -2631,7 +2632,7 @@
 
         try {
             XmlSerializer out = new FastXmlSerializer();
-            out.setOutput(fos, "utf-8");
+            out.setOutput(fos, StandardCharsets.UTF_8.name());
             writePendingOperationLocked(op, out);
             out.endDocument();
             mPendingFile.finishWrite(fos);
diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java
index 67b3695..d676b35 100644
--- a/services/core/java/com/android/server/display/PersistentDataStore.java
+++ b/services/core/java/com/android/server/display/PersistentDataStore.java
@@ -35,6 +35,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 
 import libcore.io.IoUtils;
@@ -195,7 +196,7 @@
         XmlPullParser parser;
         try {
             parser = Xml.newPullParser();
-            parser.setInput(new BufferedInputStream(is), null);
+            parser.setInput(new BufferedInputStream(is), StandardCharsets.UTF_8.name());
             loadFromXml(parser);
         } catch (IOException ex) {
             Slog.w(TAG, "Failed to load display manager persistent store data.", ex);
@@ -215,7 +216,7 @@
             boolean success = false;
             try {
                 XmlSerializer serializer = new FastXmlSerializer();
-                serializer.setOutput(new BufferedOutputStream(os), "utf-8");
+                serializer.setOutput(new BufferedOutputStream(os), StandardCharsets.UTF_8.name());
                 saveToXml(serializer);
                 serializer.flush();
                 success = true;
@@ -284,4 +285,4 @@
         serializer.endTag(null, "display-manager-state");
         serializer.endDocument();
     }
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/input/PersistentDataStore.java b/services/core/java/com/android/server/input/PersistentDataStore.java
index 92fa813..f6d7244 100644
--- a/services/core/java/com/android/server/input/PersistentDataStore.java
+++ b/services/core/java/com/android/server/input/PersistentDataStore.java
@@ -37,6 +37,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -214,7 +215,7 @@
         XmlPullParser parser;
         try {
             parser = Xml.newPullParser();
-            parser.setInput(new BufferedInputStream(is), null);
+            parser.setInput(new BufferedInputStream(is), StandardCharsets.UTF_8.name());
             loadFromXml(parser);
         } catch (IOException ex) {
             Slog.w(InputManagerService.TAG, "Failed to load input manager persistent store data.", ex);
@@ -234,7 +235,7 @@
             boolean success = false;
             try {
                 XmlSerializer serializer = new FastXmlSerializer();
-                serializer.setOutput(new BufferedOutputStream(os), "utf-8");
+                serializer.setOutput(new BufferedOutputStream(os), StandardCharsets.UTF_8.name());
                 saveToXml(serializer);
                 serializer.flush();
                 success = true;
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index b64c677..24d4f15 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -41,6 +41,7 @@
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
@@ -292,7 +293,7 @@
             try {
                 ByteArrayOutputStream baos = new ByteArrayOutputStream();
                 XmlSerializer out = new FastXmlSerializer();
-                out.setOutput(baos, "utf-8");
+                out.setOutput(baos, StandardCharsets.UTF_8.name());
                 out.startDocument(null, true);
                 out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
 
@@ -450,7 +451,7 @@
         private List<JobStatus> readJobMapImpl(FileInputStream fis)
                 throws XmlPullParserException, IOException {
             XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(fis, null);
+            parser.setInput(fis, StandardCharsets.UTF_8.name());
 
             int eventType = parser.getEventType();
             while (eventType != XmlPullParser.START_TAG &&
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 2be591b..4d101d7 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -160,6 +160,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -1242,7 +1243,7 @@
         try {
             fis = mPolicyFile.openRead();
             final XmlPullParser in = Xml.newPullParser();
-            in.setInput(fis, null);
+            in.setInput(fis, StandardCharsets.UTF_8.name());
 
             int type;
             int version = VERSION_INIT;
@@ -1377,7 +1378,7 @@
             fos = mPolicyFile.startWrite();
 
             XmlSerializer out = new FastXmlSerializer();
-            out.setOutput(fos, "utf-8");
+            out.setOutput(fos, StandardCharsets.UTF_8.name());
             out.startDocument(null, true);
 
             out.startTag(null, TAG_POLICY_LIST);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 0c47e37..9b8bd3d 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -112,6 +112,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -377,7 +378,7 @@
             try {
                 infile = mPolicyFile.openRead();
                 final XmlPullParser parser = Xml.newPullParser();
-                parser.setInput(infile, null);
+                parser.setInput(infile, StandardCharsets.UTF_8.name());
 
                 int type;
                 String tag;
@@ -435,7 +436,7 @@
 
             try {
                 final XmlSerializer out = new FastXmlSerializer();
-                out.setOutput(stream, "utf-8");
+                out.setOutput(stream, StandardCharsets.UTF_8.name());
                 out.startDocument(null, true);
                 out.startTag(null, TAG_BODY);
                 out.attribute(null, ATTR_VERSION, Integer.toString(DB_VERSION));
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 4c36fa6..955ea34 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -199,7 +199,8 @@
     @Nullable
     private String createOatDirIfSupported(PackageParser.Package pkg, String dexInstructionSet)
             throws IOException {
-        if (pkg.isSystemApp() && !pkg.isUpdatedSystemApp()) {
+        if ((pkg.isSystemApp() && !pkg.isUpdatedSystemApp()) || pkg.isForwardLocked()
+                || (!pkg.applicationInfo.isInternal())) {
             return null;
         }
         File codePath = new File(pkg.codePath);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 95d7a52..90370cc 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -94,6 +94,7 @@
 import java.io.FileOutputStream;
 import java.io.FilenameFilter;
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.security.SecureRandom;
 import java.util.ArrayList;
 import java.util.List;
@@ -307,7 +308,7 @@
         try {
             fis = mSessionsFile.openRead();
             final XmlPullParser in = Xml.newPullParser();
-            in.setInput(fis, null);
+            in.setInput(fis, StandardCharsets.UTF_8.name());
 
             int type;
             while ((type = in.next()) != END_DOCUMENT) {
@@ -398,7 +399,7 @@
             fos = mSessionsFile.startWrite();
 
             XmlSerializer out = new FastXmlSerializer();
-            out.setOutput(fos, "utf-8");
+            out.setOutput(fos, StandardCharsets.UTF_8.name());
             out.startDocument(null, true);
             out.startTag(null, TAG_SESSIONS);
             final int size = mSessions.size();
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 3f0e8b0..34ed88d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -5494,7 +5494,6 @@
         }
 
         final String path = scanFile.getPath();
-        final String codePath = pkg.applicationInfo.getCodePath();
         final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting);
         if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp()) {
             setBundledAppAbisAndRoots(pkg, pkgSetting);
@@ -5520,128 +5519,21 @@
 
             setNativeLibraryPaths(pkg);
         } else {
-            // TODO: We can probably be smarter about this stuff. For installed apps,
-            // we can calculate this information at install time once and for all. For
-            // system apps, we can probably assume that this information doesn't change
-            // after the first boot scan. As things stand, we do lots of unnecessary work.
-
-            // Give ourselves some initial paths; we'll come back for another
-            // pass once we've determined ABI below.
-            setNativeLibraryPaths(pkg);
-
-            final boolean isAsec = pkg.isForwardLocked() || isExternal(pkg);
-            final String nativeLibraryRootStr = pkg.applicationInfo.nativeLibraryRootDir;
-            final boolean useIsaSpecificSubdirs = pkg.applicationInfo.nativeLibraryRootRequiresIsa;
-
-            NativeLibraryHelper.Handle handle = null;
-            try {
-                handle = NativeLibraryHelper.Handle.create(scanFile);
-                // TODO(multiArch): This can be null for apps that didn't go through the
-                // usual installation process. We can calculate it again, like we
-                // do during install time.
+            if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
+                deriveNonSystemPackageAbi(pkg, scanFile, cpuAbiOverride, true /* extract libs */);
+            } else {
+                // TODO: We need this second call to derive in two cases :
                 //
-                // TODO(multiArch): Why do we need to rescan ASEC apps again ? It seems totally
-                // unnecessary.
-                final File nativeLibraryRoot = new File(nativeLibraryRootStr);
-
-                // Null out the abis so that they can be recalculated.
-                pkg.applicationInfo.primaryCpuAbi = null;
-                pkg.applicationInfo.secondaryCpuAbi = null;
-                if (isMultiArch(pkg.applicationInfo)) {
-                    // Warn if we've set an abiOverride for multi-lib packages..
-                    // By definition, we need to copy both 32 and 64 bit libraries for
-                    // such packages.
-                    if (pkg.cpuAbiOverride != null
-                            && !NativeLibraryHelper.CLEAR_ABI_OVERRIDE.equals(pkg.cpuAbiOverride)) {
-                        Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
-                    }
-
-                    int abi32 = PackageManager.NO_NATIVE_LIBRARIES;
-                    int abi64 = PackageManager.NO_NATIVE_LIBRARIES;
-                    if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
-                        if (isAsec) {
-                            abi32 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS);
-                        } else {
-                            abi32 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
-                                    nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS,
-                                    useIsaSpecificSubdirs);
-                        }
-                    }
-
-                    maybeThrowExceptionForMultiArchCopy(
-                            "Error unpackaging 32 bit native libs for multiarch app.", abi32);
-
-                    if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
-                        if (isAsec) {
-                            abi64 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS);
-                        } else {
-                            abi64 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
-                                    nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS,
-                                    useIsaSpecificSubdirs);
-                        }
-                    }
-
-                    maybeThrowExceptionForMultiArchCopy(
-                            "Error unpackaging 64 bit native libs for multiarch app.", abi64);
-
-                    if (abi64 >= 0) {
-                        pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[abi64];
-                    }
-
-                    if (abi32 >= 0) {
-                        final String abi = Build.SUPPORTED_32_BIT_ABIS[abi32];
-                        if (abi64 >= 0) {
-                            pkg.applicationInfo.secondaryCpuAbi = abi;
-                        } else {
-                            pkg.applicationInfo.primaryCpuAbi = abi;
-                        }
-                    }
-                } else {
-                    String[] abiList = (cpuAbiOverride != null) ?
-                            new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;
-
-                    // Enable gross and lame hacks for apps that are built with old
-                    // SDK tools. We must scan their APKs for renderscript bitcode and
-                    // not launch them if it's present. Don't bother checking on devices
-                    // that don't have 64 bit support.
-                    boolean needsRenderScriptOverride = false;
-                    if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null &&
-                            NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
-                        abiList = Build.SUPPORTED_32_BIT_ABIS;
-                        needsRenderScriptOverride = true;
-                    }
-
-                    final int copyRet;
-                    if (isAsec) {
-                        copyRet = NativeLibraryHelper.findSupportedAbi(handle, abiList);
-                    } else {
-                        copyRet = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
-                                nativeLibraryRoot, abiList, useIsaSpecificSubdirs);
-                    }
-
-                    if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
-                        throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
-                                "Error unpackaging native libs for app, errorCode=" + copyRet);
-                    }
-
-                    if (copyRet >= 0) {
-                        pkg.applicationInfo.primaryCpuAbi = abiList[copyRet];
-                    } else if (copyRet == PackageManager.NO_NATIVE_LIBRARIES && cpuAbiOverride != null) {
-                        pkg.applicationInfo.primaryCpuAbi = cpuAbiOverride;
-                    } else if (needsRenderScriptOverride) {
-                        pkg.applicationInfo.primaryCpuAbi = abiList[0];
-                    }
-                }
-            } catch (IOException ioe) {
-                Slog.e(TAG, "Unable to get canonical file " + ioe.toString());
-            } finally {
-                IoUtils.closeQuietly(handle);
+                // - To update the native library paths based on the final install location.
+                // - We don't call dexopt when moving packages, and so we have to scan again.
+                //
+                // We can simplify this and avoid having to scan the package again by letting
+                // scanPackageLI know if the current install was a move (and deriving things only
+                // in that case) and by "reparenting" the native lib directory in the case of
+                // a normal (non-move) install.
+                deriveNonSystemPackageAbi(pkg, scanFile, cpuAbiOverride, false /* extract libs */);
             }
 
-            // Now that we've calculated the ABIs and determined if it's an internal app,
-            // we will go ahead and populate the nativeLibraryPath.
-            setNativeLibraryPaths(pkg);
-
             if (DEBUG_INSTALL) Slog.i(TAG, "Linking native library dir for " + path);
             final int[] userIds = sUserManager.getUserIds();
             synchronized (mInstallLock) {
@@ -5670,9 +5562,21 @@
                     Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0];
         }
 
+        // If there's a mismatch between the abi-override in the package setting
+        // and the abiOverride specified for the install. Warn about this because we
+        // would've already compiled the app without taking the package setting into
+        // account.
+        if ((scanFlags & SCAN_NO_DEX) == 0 && (scanFlags & SCAN_NEW_INSTALL) != 0) {
+            if (cpuAbiOverride == null && pkgSetting.cpuAbiOverrideString != null) {
+                Slog.w(TAG, "Ignoring persisted ABI override " + cpuAbiOverride +
+                        " for package: " + pkg.packageName);
+            }
+        }
+
         pkgSetting.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi;
         pkgSetting.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi;
         pkgSetting.cpuAbiOverrideString = cpuAbiOverride;
+
         // Copy the derived override back to the parsed package, so that we can
         // update the package settings accordingly.
         pkg.cpuAbiOverride = cpuAbiOverride;
@@ -6176,6 +6080,144 @@
     }
 
     /**
+     * Derive the ABI of a non-system package located at {@code scanFile}. This information
+     * is derived purely on the basis of the contents of {@code scanFile} and
+     * {@code cpuAbiOverride}.
+     *
+     * If {@code extractLibs} is true, native libraries are extracted from the app if required.
+     */
+    public void deriveNonSystemPackageAbi(PackageParser.Package pkg, File scanFile,
+                                          String cpuAbiOverride, boolean extractLibs)
+            throws PackageManagerException {
+        // TODO: We can probably be smarter about this stuff. For installed apps,
+        // we can calculate this information at install time once and for all. For
+        // system apps, we can probably assume that this information doesn't change
+        // after the first boot scan. As things stand, we do lots of unnecessary work.
+
+        // Give ourselves some initial paths; we'll come back for another
+        // pass once we've determined ABI below.
+        setNativeLibraryPaths(pkg);
+
+        // We would never need to extract libs for forward-locked and external packages,
+        // since the container service will do it for us.
+        if (pkg.isForwardLocked() || isExternal(pkg)) {
+            extractLibs = false;
+        }
+
+        final String nativeLibraryRootStr = pkg.applicationInfo.nativeLibraryRootDir;
+        final boolean useIsaSpecificSubdirs = pkg.applicationInfo.nativeLibraryRootRequiresIsa;
+
+        NativeLibraryHelper.Handle handle = null;
+        try {
+            handle = NativeLibraryHelper.Handle.create(scanFile);
+            // TODO(multiArch): This can be null for apps that didn't go through the
+            // usual installation process. We can calculate it again, like we
+            // do during install time.
+            //
+            // TODO(multiArch): Why do we need to rescan ASEC apps again ? It seems totally
+            // unnecessary.
+            final File nativeLibraryRoot = new File(nativeLibraryRootStr);
+
+            // Null out the abis so that they can be recalculated.
+            pkg.applicationInfo.primaryCpuAbi = null;
+            pkg.applicationInfo.secondaryCpuAbi = null;
+            if (isMultiArch(pkg.applicationInfo)) {
+                // Warn if we've set an abiOverride for multi-lib packages..
+                // By definition, we need to copy both 32 and 64 bit libraries for
+                // such packages.
+                if (pkg.cpuAbiOverride != null
+                        && !NativeLibraryHelper.CLEAR_ABI_OVERRIDE.equals(pkg.cpuAbiOverride)) {
+                    Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
+                }
+
+                int abi32 = PackageManager.NO_NATIVE_LIBRARIES;
+                int abi64 = PackageManager.NO_NATIVE_LIBRARIES;
+                if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
+                    if (extractLibs) {
+                        abi32 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
+                                nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS,
+                                useIsaSpecificSubdirs);
+                    } else {
+                        abi32 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS);
+                    }
+                }
+
+                maybeThrowExceptionForMultiArchCopy(
+                        "Error unpackaging 32 bit native libs for multiarch app.", abi32);
+
+                if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
+                    if (extractLibs) {
+                        abi64 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
+                                nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS,
+                                useIsaSpecificSubdirs);
+                    } else {
+                        abi64 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS);
+                    }
+                }
+
+                maybeThrowExceptionForMultiArchCopy(
+                        "Error unpackaging 64 bit native libs for multiarch app.", abi64);
+
+                if (abi64 >= 0) {
+                    pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[abi64];
+                }
+
+                if (abi32 >= 0) {
+                    final String abi = Build.SUPPORTED_32_BIT_ABIS[abi32];
+                    if (abi64 >= 0) {
+                        pkg.applicationInfo.secondaryCpuAbi = abi;
+                    } else {
+                        pkg.applicationInfo.primaryCpuAbi = abi;
+                    }
+                }
+            } else {
+                String[] abiList = (cpuAbiOverride != null) ?
+                        new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;
+
+                // Enable gross and lame hacks for apps that are built with old
+                // SDK tools. We must scan their APKs for renderscript bitcode and
+                // not launch them if it's present. Don't bother checking on devices
+                // that don't have 64 bit support.
+                boolean needsRenderScriptOverride = false;
+                if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null &&
+                        NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
+                    abiList = Build.SUPPORTED_32_BIT_ABIS;
+                    needsRenderScriptOverride = true;
+                }
+
+                final int copyRet;
+                if (extractLibs) {
+                    copyRet = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
+                            nativeLibraryRoot, abiList, useIsaSpecificSubdirs);
+                } else {
+                    copyRet = NativeLibraryHelper.findSupportedAbi(handle, abiList);
+                }
+
+                if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
+                    throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+                            "Error unpackaging native libs for app, errorCode=" + copyRet);
+                }
+
+                if (copyRet >= 0) {
+                    pkg.applicationInfo.primaryCpuAbi = abiList[copyRet];
+                } else if (copyRet == PackageManager.NO_NATIVE_LIBRARIES && cpuAbiOverride != null) {
+                    pkg.applicationInfo.primaryCpuAbi = cpuAbiOverride;
+                } else if (needsRenderScriptOverride) {
+                    pkg.applicationInfo.primaryCpuAbi = abiList[0];
+                }
+            }
+        } catch (IOException ioe) {
+            Slog.e(TAG, "Unable to get canonical file " + ioe.toString());
+        } finally {
+            IoUtils.closeQuietly(handle);
+        }
+
+        // Now that we've calculated the ABIs and determined if it's an internal app,
+        // we will go ahead and populate the nativeLibraryPath.
+        setNativeLibraryPaths(pkg);
+    }
+
+    /**
      * Adjusts ABIs for a set of packages belonging to a shared user so that they all match.
      * i.e, so that all packages can be run inside a single process if required.
      *
@@ -10254,7 +10296,7 @@
         boolean forwardLocked = ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
         boolean onSd = ((installFlags & PackageManager.INSTALL_EXTERNAL) != 0);
         boolean replace = false;
-        final int scanFlags = SCAN_NEW_INSTALL | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE;
+        int scanFlags = SCAN_NEW_INSTALL | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE;
         // Result object to be returned
         res.returnCode = PackageManager.INSTALL_SUCCEEDED;
 
@@ -10421,13 +10463,27 @@
             return;
         }
 
-        // Run dexopt before old package gets removed, to minimize time when app is not available
-        int result = mPackageDexOptimizer
-                .performDexOpt(pkg, null /* instruction sets */, true /* forceDex */,
-                        false /* defer */, false /* inclDependencies */);
-        if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
-            res.setError(INSTALL_FAILED_DEXOPT, "Dexopt failed for " + pkg.codePath);
-            return;
+        // If app directory is not writable, dexopt will be called after the rename
+        if (!forwardLocked && pkg.applicationInfo.isInternal()) {
+            // Enable SCAN_NO_DEX flag to skip dexopt at a later stage
+            scanFlags |= SCAN_NO_DEX;
+            try {
+                deriveNonSystemPackageAbi(pkg, new File(pkg.codePath), args.abiOverride,
+                        true /* extract libs */);
+            } catch (PackageManagerException pme) {
+                Slog.e(TAG, "Error deriving application ABI", pme);
+                res.setError(INSTALL_FAILED_INTERNAL_ERROR, "Error deriving application ABI");
+                return;
+            }
+
+            // Run dexopt before old package gets removed, to minimize time when app is unavailable
+            int result = mPackageDexOptimizer
+                    .performDexOpt(pkg, null /* instruction sets */, true /* forceDex */,
+                            false /* defer */, false /* inclDependencies */);
+            if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
+                res.setError(INSTALL_FAILED_DEXOPT, "Dexopt failed for " + pkg.codePath);
+                return;
+            }
         }
 
         if (!args.doRename(res.returnCode, pkg, oldCodePath)) {
@@ -10435,13 +10491,12 @@
             return;
         }
 
-        // Call with SCAN_NO_DEX, since dexopt has already been made
         if (replace) {
-            replacePackageLI(pkg, parseFlags, scanFlags | SCAN_REPLACING | SCAN_NO_DEX, args.user,
+            replacePackageLI(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,
                     installerPackageName, res);
         } else {
-            installNewPackageLI(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES
-                            | SCAN_NO_DEX, args.user, installerPackageName, res);
+            installNewPackageLI(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
+                    args.user, installerPackageName, res);
         }
         synchronized (mPackages) {
             final PackageSetting ps = mSettings.mPackages.get(pkgName);
@@ -12443,7 +12498,7 @@
                 BufferedOutputStream str = new BufferedOutputStream(fout);
                 XmlSerializer serializer = new FastXmlSerializer();
                 try {
-                    serializer.setOutput(str, "utf-8");
+                    serializer.setOutput(str, StandardCharsets.UTF_8.name());
                     serializer.startDocument(null, true);
                     serializer.setFeature(
                             "http://xmlpull.org/v1/doc/features.html#indent-output", true);
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index b820d7e8..201d443 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -76,6 +76,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -1083,7 +1084,7 @@
                 str = new FileInputStream(userPackagesStateFile);
             }
             final XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(str, null);
+            parser.setInput(str, StandardCharsets.UTF_8.name());
 
             int type;
             while ((type=parser.next()) != XmlPullParser.START_TAG
@@ -1297,7 +1298,7 @@
             final BufferedOutputStream str = new BufferedOutputStream(fstr);
 
             final XmlSerializer serializer = new FastXmlSerializer();
-            serializer.setOutput(str, "utf-8");
+            serializer.setOutput(str, StandardCharsets.UTF_8.name());
             serializer.startDocument(null, true);
             serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
 
@@ -1538,7 +1539,7 @@
 
             //XmlSerializer serializer = XmlUtils.serializerInstance();
             XmlSerializer serializer = new FastXmlSerializer();
-            serializer.setOutput(str, "utf-8");
+            serializer.setOutput(str, StandardCharsets.UTF_8.name());
             serializer.startDocument(null, true);
             serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
 
@@ -1987,7 +1988,7 @@
                 str = new FileInputStream(mSettingsFilename);
             }
             XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(str, null);
+            parser.setInput(str, StandardCharsets.UTF_8.name());
 
             int type;
             while ((type = parser.next()) != XmlPullParser.START_TAG
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index f84cb30..123639e 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -70,6 +70,7 @@
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -537,6 +538,28 @@
      * Check if we've hit the limit of how many users can be created.
      */
     private boolean isUserLimitReachedLocked() {
+        return getAliveUsersExcludingGuestsCountLocked() >= UserManager.getMaxSupportedUsers();
+    }
+
+    @Override
+    public boolean canAddMoreManagedProfiles() {
+        checkManageUsersPermission("check if more managed profiles can be added.");
+        if (ActivityManager.isLowRamDeviceStatic()) {
+            return false;
+        }
+        synchronized(mPackagesLock) {
+            // Limit number of managed profiles that can be created
+            if (numberOfUsersOfTypeLocked(UserInfo.FLAG_MANAGED_PROFILE, true)
+                    >= MAX_MANAGED_PROFILES) {
+                return false;
+            }
+            int usersCount = getAliveUsersExcludingGuestsCountLocked();
+            // We allow creating a managed profile in the special case where there is only one user.
+            return usersCount == 1 || usersCount < UserManager.getMaxSupportedUsers();
+        }
+    }
+
+    private int getAliveUsersExcludingGuestsCountLocked() {
         int aliveUserCount = 0;
         final int totalUserCount = mUsers.size();
         // Skip over users being removed
@@ -547,7 +570,7 @@
                 aliveUserCount++;
             }
         }
-        return aliveUserCount >= UserManager.getMaxSupportedUsers();
+        return aliveUserCount;
     }
 
     /**
@@ -618,7 +641,7 @@
         try {
             fis = userListFile.openRead();
             XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(fis, null);
+            parser.setInput(fis, StandardCharsets.UTF_8.name());
             int type;
             while ((type = parser.next()) != XmlPullParser.START_TAG
                     && type != XmlPullParser.END_DOCUMENT) {
@@ -764,7 +787,7 @@
 
             // XmlSerializer serializer = XmlUtils.serializerInstance();
             final XmlSerializer serializer = new FastXmlSerializer();
-            serializer.setOutput(bos, "utf-8");
+            serializer.setOutput(bos, StandardCharsets.UTF_8.name());
             serializer.startDocument(null, true);
             serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
 
@@ -838,7 +861,7 @@
 
             // XmlSerializer serializer = XmlUtils.serializerInstance();
             final XmlSerializer serializer = new FastXmlSerializer();
-            serializer.setOutput(bos, "utf-8");
+            serializer.setOutput(bos, StandardCharsets.UTF_8.name());
             serializer.startDocument(null, true);
             serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
 
@@ -922,7 +945,7 @@
                     new AtomicFile(new File(mUsersDir, Integer.toString(id) + XML_SUFFIX));
             fis = userFile.openRead();
             XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(fis, null);
+            parser.setInput(fis, StandardCharsets.UTF_8.name());
             int type;
             while ((type = parser.next()) != XmlPullParser.START_TAG
                     && type != XmlPullParser.END_DOCUMENT) {
@@ -1152,7 +1175,11 @@
             Log.w(LOG_TAG, "Cannot add user. DISALLOW_ADD_USER is enabled.");
             return null;
         }
+        if (ActivityManager.isLowRamDeviceStatic()) {
+            return null;
+        }
         final boolean isGuest = (flags & UserInfo.FLAG_GUEST) != 0;
+        final boolean isManagedProfile = (flags & UserInfo.FLAG_MANAGED_PROFILE) != 0;
         final long ident = Binder.clearCallingIdentity();
         UserInfo userInfo = null;
         try {
@@ -1163,21 +1190,18 @@
                         parent = getUserInfoLocked(parentId);
                         if (parent == null) return null;
                     }
-                    // If we're not adding a guest user and the limit has been reached,
-                    // cannot add a user.
-                    if (!isGuest && isUserLimitReachedLocked()) {
+                    if (isManagedProfile && !canAddMoreManagedProfiles()) {
+                        return null;
+                    }
+                    if (!isGuest && !isManagedProfile && isUserLimitReachedLocked()) {
+                        // If we're not adding a guest user or a managed profile and the limit has
+                        // been reached, cannot add a user.
                         return null;
                     }
                     // If we're adding a guest and there already exists one, bail.
                     if (isGuest && findCurrentGuestUserLocked() != null) {
                         return null;
                     }
-                    // Limit number of managed profiles that can be created
-                    if ((flags & UserInfo.FLAG_MANAGED_PROFILE) != 0
-                            && numberOfUsersOfTypeLocked(UserInfo.FLAG_MANAGED_PROFILE, true)
-                                >= MAX_MANAGED_PROFILES) {
-                        return null;
-                    }
                     int userId = getNextAvailableIdLocked();
                     userInfo = new UserInfo(userId, name, null, flags);
                     File userPath = new File(mBaseUserPath, Integer.toString(userId));
@@ -1664,7 +1688,7 @@
                             packageToRestrictionsFileName(packageName)));
             fis = restrictionsFile.openRead();
             XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(fis, null);
+            parser.setInput(fis, StandardCharsets.UTF_8.name());
             int type;
             while ((type = parser.next()) != XmlPullParser.START_TAG
                     && type != XmlPullParser.END_DOCUMENT) {
@@ -1732,7 +1756,7 @@
 
             // XmlSerializer serializer = XmlUtils.serializerInstance();
             final XmlSerializer serializer = new FastXmlSerializer();
-            serializer.setOutput(bos, "utf-8");
+            serializer.setOutput(bos, StandardCharsets.UTF_8.name());
             serializer.startDocument(null, true);
             serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
 
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 9786b42..32c0fb8 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -2357,8 +2357,7 @@
     /**
      * Low-level function to reboot the device. On success, this
      * function doesn't return. If more than 20 seconds passes from
-     * the time a reboot is requested (120 seconds for reboot to
-     * recovery), this method returns.
+     * the time a reboot is requested, this method returns.
      *
      * @param reason code to pass to the kernel (e.g. "recovery"), or null.
      */
@@ -2366,27 +2365,21 @@
         if (reason == null) {
             reason = "";
         }
-        long duration;
         if (reason.equals(PowerManager.REBOOT_RECOVERY)) {
             // If we are rebooting to go into recovery, instead of
             // setting sys.powerctl directly we'll start the
             // pre-recovery service which will do some preparation for
             // recovery and then reboot for us.
-            //
-            // This preparation can take more than 20 seconds if
-            // there's a very large update package, so lengthen the
-            // timeout.  We have seen 750MB packages take 3-4 minutes
             SystemProperties.set("ctl.start", "pre-recovery");
-            duration = 300 * 1000L;
         } else {
             SystemProperties.set("sys.powerctl", "reboot," + reason);
-            duration = 20 * 1000L;
         }
         try {
-            Thread.sleep(duration);
+            Thread.sleep(20 * 1000L);
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();
         }
+        Slog.wtf(TAG, "Unexpected return from lowLevelReboot!");
     }
 
     @Override // Watchdog.Monitor implementation
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index f61a0c8..4c14c47 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
- 
+
 package com.android.server.power;
 
 import android.app.ActivityManagerNative;
@@ -43,6 +43,8 @@
 import android.os.SystemVibrator;
 import android.os.storage.IMountService;
 import android.os.storage.IMountShutdownObserver;
+import android.system.ErrnoException;
+import android.system.Os;
 
 import com.android.internal.telephony.ITelephony;
 import com.android.server.pm.PackageManagerService;
@@ -50,6 +52,11 @@
 import android.util.Log;
 import android.view.WindowManager;
 
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
 public final class ShutdownThread extends Thread {
     // constants
     private static final String TAG = "ShutdownThread";
@@ -58,16 +65,28 @@
     private static final int MAX_BROADCAST_TIME = 10*1000;
     private static final int MAX_SHUTDOWN_WAIT_TIME = 20*1000;
     private static final int MAX_RADIO_WAIT_TIME = 12*1000;
+    private static final int MAX_UNCRYPT_WAIT_TIME = 15*60*1000;
+    // constants for progress bar. the values are roughly estimated based on timeout.
+    private static final int BROADCAST_STOP_PERCENT = 2;
+    private static final int ACTIVITY_MANAGER_STOP_PERCENT = 4;
+    private static final int PACKAGE_MANAGER_STOP_PERCENT = 6;
+    private static final int RADIO_STOP_PERCENT = 18;
+    private static final int MOUNT_SERVICE_STOP_PERCENT = 20;
 
     // length of vibration before shutting down
     private static final int SHUTDOWN_VIBRATE_MS = 500;
-    
+
     // state tracking
     private static Object sIsStartedGuard = new Object();
     private static boolean sIsStarted = false;
-    
+
+    // uncrypt status files
+    private static final String UNCRYPT_STATUS_FILE = "/cache/recovery/uncrypt_status";
+    private static final String UNCRYPT_PACKAGE_FILE = "/cache/recovery/uncrypt_file";
+
     private static boolean mReboot;
     private static boolean mRebootSafeMode;
+    private static boolean mRebootUpdate;
     private static String mRebootReason;
 
     // Provides shutdown assurance in case the system_server is killed
@@ -93,10 +112,11 @@
     private Handler mHandler;
 
     private static AlertDialog sConfirmDialog;
-    
+    private ProgressDialog mProgressDialog;
+
     private ShutdownThread() {
     }
- 
+
     /**
      * Request a clean shutdown, waiting for subsystems to clean up their
      * state etc.  Must be called from a Looper thread in which its UI
@@ -190,6 +210,7 @@
     public static void reboot(final Context context, String reason, boolean confirm) {
         mReboot = true;
         mRebootSafeMode = false;
+        mRebootUpdate = false;
         mRebootReason = reason;
         shutdownInner(context, confirm);
     }
@@ -204,6 +225,7 @@
     public static void rebootSafeMode(final Context context, boolean confirm) {
         mReboot = true;
         mRebootSafeMode = true;
+        mRebootUpdate = false;
         mRebootReason = null;
         shutdownInner(context, confirm);
     }
@@ -217,17 +239,50 @@
             sIsStarted = true;
         }
 
-        // throw up an indeterminate system dialog to indicate radio is
-        // shutting down.
+        // Throw up a system dialog to indicate the device is rebooting / shutting down.
         ProgressDialog pd = new ProgressDialog(context);
-        pd.setTitle(context.getText(com.android.internal.R.string.power_off));
-        pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
-        pd.setIndeterminate(true);
+
+        // Path 1: Reboot to recovery and install the update
+        //   Condition: mRebootReason == REBOOT_RECOVERY and mRebootUpdate == True
+        //   (mRebootUpdate is set by checking if /cache/recovery/uncrypt_file exists.)
+        //   UI: progress bar
+        //
+        // Path 2: Reboot to recovery for factory reset
+        //   Condition: mRebootReason == REBOOT_RECOVERY
+        //   UI: spinning circle only (no progress bar)
+        //
+        // Path 3: Regular reboot / shutdown
+        //   Condition: Otherwise
+        //   UI: spinning circle only (no progress bar)
+        if (PowerManager.REBOOT_RECOVERY.equals(mRebootReason)) {
+            mRebootUpdate = new File(UNCRYPT_PACKAGE_FILE).exists();
+            if (mRebootUpdate) {
+                pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_update_title));
+                pd.setMessage(context.getText(
+                        com.android.internal.R.string.reboot_to_update_prepare));
+                pd.setMax(100);
+                pd.setProgressNumberFormat(null);
+                pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
+                pd.setProgress(0);
+                pd.setIndeterminate(false);
+            } else {
+                // Factory reset path. Set the dialog message accordingly.
+                pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_reset_title));
+                pd.setMessage(context.getText(
+                        com.android.internal.R.string.reboot_to_reset_message));
+                pd.setIndeterminate(true);
+            }
+        } else {
+            pd.setTitle(context.getText(com.android.internal.R.string.power_off));
+            pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
+            pd.setIndeterminate(true);
+        }
         pd.setCancelable(false);
         pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
 
         pd.show();
 
+        sInstance.mProgressDialog = pd;
         sInstance.mContext = context;
         sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
 
@@ -301,14 +356,14 @@
         }
 
         Log.i(TAG, "Sending shutdown broadcast...");
-        
+
         // First send the high-level shut down broadcast.
         mActionDone = false;
         Intent intent = new Intent(Intent.ACTION_SHUTDOWN);
         intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
         mContext.sendOrderedBroadcastAsUser(intent,
                 UserHandle.ALL, null, br, mHandler, 0, null, null);
-        
+
         final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;
         synchronized (mActionDoneSync) {
             while (!mActionDone) {
@@ -316,16 +371,23 @@
                 if (delay <= 0) {
                     Log.w(TAG, "Shutdown broadcast timed out");
                     break;
+                } else if (mRebootUpdate) {
+                    int status = (int)((MAX_BROADCAST_TIME - delay) * 1.0 *
+                            BROADCAST_STOP_PERCENT / MAX_BROADCAST_TIME);
+                    sInstance.setRebootProgress(status, null);
                 }
                 try {
-                    mActionDoneSync.wait(delay);
+                    mActionDoneSync.wait(Math.min(delay, PHONE_STATE_POLL_SLEEP_MSEC));
                 } catch (InterruptedException e) {
                 }
             }
         }
-        
+        if (mRebootUpdate) {
+            sInstance.setRebootProgress(BROADCAST_STOP_PERCENT, null);
+        }
+
         Log.i(TAG, "Shutting down activity manager...");
-        
+
         final IActivityManager am =
             ActivityManagerNative.asInterface(ServiceManager.checkService("activity"));
         if (am != null) {
@@ -334,6 +396,9 @@
             } catch (RemoteException e) {
             }
         }
+        if (mRebootUpdate) {
+            sInstance.setRebootProgress(ACTIVITY_MANAGER_STOP_PERCENT, null);
+        }
 
         Log.i(TAG, "Shutting down package manager...");
 
@@ -342,9 +407,15 @@
         if (pm != null) {
             pm.shutdown();
         }
+        if (mRebootUpdate) {
+            sInstance.setRebootProgress(PACKAGE_MANAGER_STOP_PERCENT, null);
+        }
 
         // Shutdown radios.
         shutdownRadios(MAX_RADIO_WAIT_TIME);
+        if (mRebootUpdate) {
+            sInstance.setRebootProgress(RADIO_STOP_PERCENT, null);
+        }
 
         // Shutdown MountService to ensure media is in a safe state
         IMountShutdownObserver observer = new IMountShutdownObserver.Stub() {
@@ -376,18 +447,44 @@
                 if (delay <= 0) {
                     Log.w(TAG, "Shutdown wait timed out");
                     break;
+                } else if (mRebootUpdate) {
+                    int status = (int)((MAX_SHUTDOWN_WAIT_TIME - delay) * 1.0 *
+                            (MOUNT_SERVICE_STOP_PERCENT - RADIO_STOP_PERCENT) /
+                            MAX_SHUTDOWN_WAIT_TIME);
+                    status += RADIO_STOP_PERCENT;
+                    sInstance.setRebootProgress(status, null);
                 }
                 try {
-                    mActionDoneSync.wait(delay);
+                    mActionDoneSync.wait(Math.min(delay, PHONE_STATE_POLL_SLEEP_MSEC));
                 } catch (InterruptedException e) {
                 }
             }
         }
+        if (mRebootUpdate) {
+            sInstance.setRebootProgress(MOUNT_SERVICE_STOP_PERCENT, null);
+
+            // If it's to reboot to install update, invoke uncrypt via init service.
+            uncrypt();
+        }
 
         rebootOrShutdown(mContext, mReboot, mRebootReason);
     }
 
-    private void shutdownRadios(int timeout) {
+    private void setRebootProgress(final int progress, final CharSequence message) {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                if (mProgressDialog != null) {
+                    mProgressDialog.setProgress(progress);
+                    if (message != null) {
+                        mProgressDialog.setMessage(message);
+                    }
+                }
+            }
+        });
+    }
+
+    private void shutdownRadios(final int timeout) {
         // If a radio is wedged, disabling it may hang so we do this work in another thread,
         // just in case.
         final long endTime = SystemClock.elapsedRealtime() + timeout;
@@ -442,7 +539,15 @@
 
                 Log.i(TAG, "Waiting for NFC, Bluetooth and Radio...");
 
-                while (SystemClock.elapsedRealtime() < endTime) {
+                long delay = endTime - SystemClock.elapsedRealtime();
+                while (delay > 0) {
+                    if (mRebootUpdate) {
+                        int status = (int)((timeout - delay) * 1.0 *
+                                (RADIO_STOP_PERCENT - PACKAGE_MANAGER_STOP_PERCENT) / timeout);
+                        status += PACKAGE_MANAGER_STOP_PERCENT;
+                        sInstance.setRebootProgress(status, null);
+                    }
+
                     if (!bluetoothOff) {
                         try {
                             bluetoothOff = !bluetooth.isEnabled();
@@ -483,6 +588,8 @@
                         break;
                     }
                     SystemClock.sleep(PHONE_STATE_POLL_SLEEP_MSEC);
+
+                    delay = endTime - SystemClock.elapsedRealtime();
                 }
             }
         };
@@ -531,4 +638,82 @@
         Log.i(TAG, "Performing low-level shutdown...");
         PowerManagerService.lowLevelShutdown();
     }
+
+    private void uncrypt() {
+        Log.i(TAG, "Calling uncrypt and monitoring the progress...");
+
+        final boolean[] done = new boolean[1];
+        done[0] = false;
+        Thread t = new Thread() {
+            @Override
+            public void run() {
+                // Create the status pipe file to communicate with /system/bin/uncrypt.
+                new File(UNCRYPT_STATUS_FILE).delete();
+                try {
+                    Os.mkfifo(UNCRYPT_STATUS_FILE, 0600);
+                } catch (ErrnoException e) {
+                    Log.w(TAG, "ErrnoException when creating named pipe \"" + UNCRYPT_STATUS_FILE +
+                            "\": " + e.getMessage());
+                }
+
+                SystemProperties.set("ctl.start", "uncrypt");
+
+                // Read the status from the pipe.
+                try (BufferedReader reader = new BufferedReader(
+                        new FileReader(UNCRYPT_STATUS_FILE))) {
+
+                    int lastStatus = Integer.MIN_VALUE;
+                    while (true) {
+                        String str = reader.readLine();
+                        try {
+                            int status = Integer.parseInt(str);
+
+                            // Avoid flooding the log with the same message.
+                            if (status == lastStatus && lastStatus != Integer.MIN_VALUE) {
+                                continue;
+                            }
+                            lastStatus = status;
+
+                            if (status >= 0 && status < 100) {
+                                // Update status
+                                Log.d(TAG, "uncrypt read status: " + status);
+                                // Scale down to [MOUNT_SERVICE_STOP_PERCENT, 100).
+                                status = (int)(status * (100.0 - MOUNT_SERVICE_STOP_PERCENT) / 100);
+                                status += MOUNT_SERVICE_STOP_PERCENT;
+                                CharSequence msg = mContext.getText(
+                                        com.android.internal.R.string.reboot_to_update_package);
+                                sInstance.setRebootProgress(status, msg);
+                            } else if (status == 100) {
+                                Log.d(TAG, "uncrypt successfully finished.");
+                                CharSequence msg = mContext.getText(
+                                        com.android.internal.R.string.reboot_to_update_reboot);
+                                sInstance.setRebootProgress(status, msg);
+                                break;
+                            } else {
+                                // Error in /system/bin/uncrypt. Or it's rebooting to recovery
+                                // to perform other operations (e.g. factory reset).
+                                Log.d(TAG, "uncrypt failed with status: " + status);
+                                break;
+                            }
+                        } catch (NumberFormatException unused) {
+                            Log.d(TAG, "uncrypt invalid status received: " + str);
+                            break;
+                        }
+                    }
+                } catch (IOException unused) {
+                    Log.w(TAG, "IOException when reading \"" + UNCRYPT_STATUS_FILE + "\".");
+                }
+                done[0] = true;
+            }
+        };
+        t.start();
+
+        try {
+            t.join(MAX_UNCRYPT_WAIT_TIME);
+        } catch (InterruptedException unused) {
+        }
+        if (!done[0]) {
+            Log.w(TAG, "Timed out waiting for uncrypt.");
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/tv/PersistentDataStore.java b/services/core/java/com/android/server/tv/PersistentDataStore.java
index fcfaaea..f9b5b9a 100644
--- a/services/core/java/com/android/server/tv/PersistentDataStore.java
+++ b/services/core/java/com/android/server/tv/PersistentDataStore.java
@@ -44,6 +44,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -167,7 +168,7 @@
         XmlPullParser parser;
         try {
             parser = Xml.newPullParser();
-            parser.setInput(new BufferedInputStream(is), null);
+            parser.setInput(new BufferedInputStream(is), StandardCharsets.UTF_8.name());
             loadFromXml(parser);
         } catch (IOException | XmlPullParserException ex) {
             Slog.w(TAG, "Failed to load tv input manager persistent store data.", ex);
@@ -200,7 +201,7 @@
             boolean success = false;
             try {
                 XmlSerializer serializer = new FastXmlSerializer();
-                serializer.setOutput(new BufferedOutputStream(os), "utf-8");
+                serializer.setOutput(new BufferedOutputStream(os), StandardCharsets.UTF_8.name());
                 saveToXml(serializer);
                 serializer.flush();
                 success = true;
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index bd2e923..9410bef 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -78,6 +78,7 @@
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
 import java.util.List;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -1108,7 +1109,7 @@
         try {
             stream = new FileOutputStream(journal.chooseForWrite(), false);
             XmlSerializer out = new FastXmlSerializer();
-            out.setOutput(stream, "utf-8");
+            out.setOutput(stream, StandardCharsets.UTF_8.name());
             out.startDocument(null, true);
 
             out.startTag(null, "wp");
@@ -1189,7 +1190,7 @@
         try {
             stream = new FileInputStream(file);
             XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(stream, null);
+            parser.setInput(stream, StandardCharsets.UTF_8.name());
 
             int type;
             do {
diff --git a/services/core/java/com/android/server/wm/DisplaySettings.java b/services/core/java/com/android/server/wm/DisplaySettings.java
index ba995f2..01f878c 100644
--- a/services/core/java/com/android/server/wm/DisplaySettings.java
+++ b/services/core/java/com/android/server/wm/DisplaySettings.java
@@ -32,6 +32,7 @@
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 
 /**
@@ -108,7 +109,7 @@
         boolean success = false;
         try {
             XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(stream, null);
+            parser.setInput(stream, StandardCharsets.UTF_8.name());
             int type;
             while ((type = parser.next()) != XmlPullParser.START_TAG
                     && type != XmlPullParser.END_DOCUMENT) {
@@ -193,7 +194,7 @@
 
         try {
             XmlSerializer out = new FastXmlSerializer();
-            out.setOutput(stream, "utf-8");
+            out.setOutput(stream, StandardCharsets.UTF_8.name());
             out.startDocument(null, true);
             out.startTag(null, "display-settings");
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 63c4461..001a6f8 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2206,6 +2206,16 @@
             } else if (changingTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
                 mLastWallpaperDisplayOffsetY = changingTarget.mWallpaperDisplayOffsetY;
             }
+            if (target.mWallpaperXStep >= 0) {
+                mLastWallpaperXStep = target.mWallpaperXStep;
+            } else if (changingTarget.mWallpaperXStep >= 0) {
+                mLastWallpaperXStep = changingTarget.mWallpaperXStep;
+            }
+            if (target.mWallpaperYStep >= 0) {
+                mLastWallpaperYStep = target.mWallpaperYStep;
+            } else if (changingTarget.mWallpaperYStep >= 0) {
+                mLastWallpaperYStep = changingTarget.mWallpaperYStep;
+            }
         }
 
         int curTokenIndex = mWallpaperTokens.size();
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
index 9fd0e09..58065e4 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
@@ -39,6 +39,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Set;
 
@@ -211,7 +212,7 @@
         try {
             InputStream input = openRead();
             XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(input, null);
+            parser.setInput(input, StandardCharsets.UTF_8.name());
             int type;
             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT) {
                 if (type!=XmlPullParser.START_TAG) {
@@ -269,7 +270,7 @@
         try {
             OutputStream outputStream = startWrite();
             XmlSerializer out = new FastXmlSerializer();
-            out.setOutput(outputStream, "utf-8");
+            out.setOutput(outputStream, StandardCharsets.UTF_8.name());
             out.startDocument(null, true);
 
             // Write device owner tag
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 40e2056..b1d1788 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -121,6 +121,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
@@ -1305,7 +1306,7 @@
         try {
             stream = new FileOutputStream(journal.chooseForWrite(), false);
             XmlSerializer out = new FastXmlSerializer();
-            out.setOutput(stream, "utf-8");
+            out.setOutput(stream, StandardCharsets.UTF_8.name());
             out.startDocument(null, true);
 
             out.startTag(null, "policies");
@@ -1403,7 +1404,7 @@
         try {
             stream = new FileInputStream(file);
             XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(stream, null);
+            parser.setInput(stream, StandardCharsets.UTF_8.name());
 
             int type;
             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
diff --git a/services/usb/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
index 37b5c51..0c67d96 100644
--- a/services/usb/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
@@ -58,6 +58,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -559,7 +560,7 @@
             try {
                 fis = new FileInputStream(sSingleUserSettingsFile);
                 XmlPullParser parser = Xml.newPullParser();
-                parser.setInput(fis, null);
+                parser.setInput(fis, StandardCharsets.UTF_8.name());
 
                 XmlUtils.nextElement(parser);
                 while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
@@ -595,7 +596,7 @@
         try {
             stream = mSettingsFile.openRead();
             XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(stream, null);
+            parser.setInput(stream, StandardCharsets.UTF_8.name());
 
             XmlUtils.nextElement(parser);
             while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
@@ -624,7 +625,7 @@
             fos = mSettingsFile.startWrite();
 
             FastXmlSerializer serializer = new FastXmlSerializer();
-            serializer.setOutput(fos, "utf-8");
+            serializer.setOutput(fos, StandardCharsets.UTF_8.name());
             serializer.startDocument(null, true);
             serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
             serializer.startTag(null, "settings");
diff --git a/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbosync.rs b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbosync.rs
index 42b1cf1..0c177ef 100644
--- a/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbosync.rs
+++ b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbosync.rs
@@ -116,7 +116,6 @@
     rs_allocation allMeshes = rsGetAllocation(gMeshes);
     int size = rsAllocationGetDimX(allMeshes);
     gLookAt = 0.0f;
-    float minX, minY, minZ, maxX, maxY, maxZ;
     for (int i = 0; i < size; i++) {
         MeshInfo_t *info = (MeshInfo_t*)rsGetElementAt(allMeshes, i);
         rsgDrawMesh(info->mMesh);
@@ -124,7 +123,6 @@
 }
 
 static void drawDescription() {
-    uint width = rsgGetWidth();
     uint height = rsgGetHeight();
     int left = 0, right = 0, top = 0, bottom = 0;
 
@@ -196,7 +194,6 @@
 
     uint32_t w = rsAllocationGetDimX(gOffscreen);
     uint32_t h = rsAllocationGetDimY(gOffscreen);
-    uint32_t numElements = w*h;
 
     rsgAllocationSyncAll(gOffscreen, RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET);
 
diff --git a/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbotest.rs b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbotest.rs
index 05ef3ac..13a3c85 100644
--- a/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbotest.rs
+++ b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbotest.rs
@@ -115,7 +115,6 @@
     rs_allocation allMeshes = rsGetAllocation(gMeshes);
     int size = rsAllocationGetDimX(allMeshes);
     gLookAt = 0.0f;
-    float minX, minY, minZ, maxX, maxY, maxZ;
     for (int i = 0; i < size; i++) {
         MeshInfo_t *info = (MeshInfo_t*)rsGetElementAt(allMeshes, i);
         rsgDrawMesh(info->mMesh);
@@ -123,7 +122,6 @@
 }
 
 static void drawDescription() {
-    uint width = rsgGetWidth();
     uint height = rsgGetHeight();
     int left = 0, right = 0, top = 0, bottom = 0;
 
diff --git a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/simplemodel.rs b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/simplemodel.rs
index de2a0a7..d3dd5b9 100644
--- a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/simplemodel.rs
+++ b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/simplemodel.rs
@@ -123,7 +123,6 @@
     rs_allocation allMeshes = rsGetAllocation(gMeshes);
     int size = rsAllocationGetDimX(allMeshes);
     gLookAt = 0.0f;
-    float minX, minY, minZ, maxX, maxY, maxZ;
     for (int i = 0; i < size; i++) {
         MeshInfo_t *info = (MeshInfo_t*)rsGetElementAt(allMeshes, i);
         rsgDrawMesh(info->mMesh);
@@ -131,7 +130,6 @@
 }
 
 void drawDescription() {
-    uint width = rsgGetWidth();
     uint height = rsgGetHeight();
     int left = 0, right = 0, top = 0, bottom = 0;
 
@@ -163,7 +161,7 @@
     rsMatrixMultiply(&matrix, &gPostureMatrix);
     rsMatrixRotate(&matrix, gRotateX, 1.0f, 0.0f, 0.0f);
     rsMatrixRotate(&matrix, gRotateY, 0.0f, 1.0f, 0.0f);
-    
+
     rsgProgramVertexLoadModelMatrix(&matrix);
 
     renderAllMeshes();
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
index 27e5b11..43cf4e0 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
@@ -85,7 +85,7 @@
     TestData testData;
     fillSurfaceParams(&testData);
 
-    rs_allocation null_alloc;
+    rs_allocation null_alloc = {0};
     rsForEach(gTestScripts[index].testScript,
               gTestScripts[index].testData,
               null_alloc,
@@ -125,7 +125,6 @@
 
 static int benchMode = 0;
 static bool benchmarkSingleTest = false;
-static int benchSubMode = 0;
 static int runningLoops = 0;
 static bool sendMsgFlag = false;
 
@@ -209,7 +208,6 @@
     drawOffscreenResult(0, 0, quadW, quadH);
 
     int left = 0, right = 0, top = 0, bottom = 0;
-    uint width = rsgGetWidth();
     uint height = rsgGetHeight();
     rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f);
     rsgBindFont(gFontSerif);
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/text_test.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/text_test.rs
index 7f10019..0f50828 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/text_test.rs
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/text_test.rs
@@ -52,7 +52,6 @@
     fonts[3] = gFontSerif;
     fonts[4] = gFontSans;
 
-    uint width = gRenderSurfaceW;
     uint height = gRenderSurfaceH;
     int left = 0, right = 0, top = 0, bottom = 0;
     rsgMeasureText(sampleText, &left, &right, &top, &bottom);
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/ui_test.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/ui_test.rs
index 5089092..e87db39 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/ui_test.rs
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/ui_test.rs
@@ -143,7 +143,6 @@
     float d = fabs(randomGauss()) * gGalaxyRadius * 0.5f + rsRand(64.0f);
     float id = d / gGalaxyRadius;
     float z = randomGauss() * 0.4f * (1.0f - id);
-    float p = -d * ELLIPSE_TWIST;
 
     if (d < gGalaxyRadius * 0.33f) {
         part->color.x = (uchar) (220 + id * 35);
@@ -305,7 +304,6 @@
     int left = 0, right = 0, top = 0, bottom = 0;
     rsgMeasureText(gSampleTextList100[0].item, &left, &right, &top, &bottom);
     float textHeight = (float)(top - bottom);
-    float textWidth = (float)(right - left);
 
     rs_matrix4x4 matrix;
     rsMatrixLoadScale(&matrix, size, size, 1.0);
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/params.rsh b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/params.rsh
index 575794b..00793c0 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/params.rsh
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/params.rsh
@@ -19,7 +19,7 @@
 #include "scenegraph_objects.rsh"
 
 //#define DEBUG_PARAMS
-static void debugParam(SgShaderParam *p, SgShaderParamData *pData) {
+static inline void debugParam(SgShaderParam *p, SgShaderParamData *pData) {
     rsDebug("____________ Param ____________", p);
     printName(pData->paramName);
     rsDebug("bufferOffset", p->bufferOffset);
@@ -44,8 +44,7 @@
     }
 }
 
-
-static void writeFloatData(float *ptr, const float4 *input, uint32_t vecSize) {
+static inline void writeFloatData(float *ptr, const float4 *input, uint32_t vecSize) {
 #ifdef DEBUG_PARAMS
     rsDebug("Writing value ", *input);
     rsDebug("Writing vec size ", vecSize);
@@ -67,7 +66,7 @@
     }
 }
 
-static bool processParam(SgShaderParam *p, SgShaderParamData *pData,
+static inline bool processParam(SgShaderParam *p, SgShaderParamData *pData,
                          uint8_t *constantBuffer,
                          const SgCamera *currentCam,
                          SgFragmentShader *shader) {
@@ -155,7 +154,7 @@
     return true;
 }
 
-static void processAllParams(rs_allocation shaderConst,
+static inline void processAllParams(rs_allocation shaderConst,
                              rs_allocation allParams,
                              const SgCamera *camera) {
     if (rsIsObject(shaderConst)) {
@@ -177,7 +176,7 @@
     }
 }
 
-static void processTextureParams(SgFragmentShader *shader) {
+static inline void processTextureParams(SgFragmentShader *shader) {
     int numParams = 0;
     if (rsIsObject(shader->shaderTextureParams)) {
         numParams = rsAllocationGetDimX(shader->shaderTextureParams);
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/render.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/render.rs
index 8a73dbd..205b2cb 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/render.rs
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/render.rs
@@ -78,7 +78,7 @@
     if (rsIsObject(renderState->pr)) {
         rsgBindProgramRaster(renderState->pr);
     } else {
-        rs_program_raster pr;
+        rs_program_raster pr = {0};
         rsgBindProgramRaster(pr);
     }
 
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/scenegraph_objects.rsh b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/scenegraph_objects.rsh
index bdca3ab..90ae212 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/scenegraph_objects.rsh
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/scenegraph_objects.rsh
@@ -208,7 +208,7 @@
     rs_allocation texture;
 } SgTexture;
 
-static void printName(rs_allocation name) {
+static inline void printName(rs_allocation name) {
     if (!rsIsObject(name)) {
         rsDebug("no name", 0);
         return;
@@ -217,7 +217,7 @@
     rsDebug((const char*)rsGetElementAt(name, 0), 0);
 }
 
-static void printCameraInfo(const SgCamera *cam) {
+static inline void printCameraInfo(const SgCamera *cam) {
     rsDebug("***** Camera information. ptr:", cam);
     printName(cam->name);
     const SgTransform *camTransform = (const SgTransform *)rsGetElementAt(cam->transformMatrix, 0);
@@ -233,7 +233,7 @@
     rsDebug("View: ", &cam->view);
 }
 
-static void printLightInfo(const SgLight *light) {
+static inline void printLightInfo(const SgLight *light) {
     rsDebug("***** Light information. ptr:", light);
     printName(light->name);
     const SgTransform *lTransform = (const SgTransform *)rsGetElementAt(light->transformMatrix, 0);
@@ -246,7 +246,7 @@
     rsDebug("Type: ", light->type);
 }
 
-static void getCameraRay(const SgCamera *cam, int screenX, int screenY, float3 *pnt, float3 *vec) {
+static inline void getCameraRay(const SgCamera *cam, int screenX, int screenY, float3 *pnt, float3 *vec) {
     rsDebug("=================================", screenX);
     rsDebug("Point X", screenX);
     rsDebug("Point Y", screenY);
@@ -290,7 +290,7 @@
     *pnt = cam->position.xyz;
 }
 
-static bool intersect(const SgRenderable *obj, float3 pnt, float3 vec) {
+static inline bool intersect(const SgRenderable *obj, float3 pnt, float3 vec) {
     // Solving for t^2 + Bt + C = 0
     float3 originMinusCenter = pnt - obj->worldBoundingSphere.xyz;
     float B = dot(originMinusCenter, vec) * 2.0f;
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/transform.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/transform.rs
index 941b5a8..1d0b5be 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/transform.rs
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/scenegraph/transform.rs
@@ -26,6 +26,7 @@
 } ParentData;
 
 //#define DEBUG_TRANSFORMS
+/* Unused function:
 static void debugTransform(SgTransform *data, const ParentData *parent) {
     rsDebug("****** <Transform> ******", (int)data);
     printName(data->name);
@@ -53,6 +54,7 @@
     rsDebug("timestamp", data->timestamp);
     rsDebug("****** </Transform> ******", (int)data);
 }
+*/
 
 static void appendTransformation(int type, float4 data, rs_matrix4x4 *mat) {
     rs_matrix4x4 temp;
@@ -119,7 +121,7 @@
     }
 
     if (rsIsObject(data->children)) {
-        rs_allocation nullAlloc;
+        rs_allocation nullAlloc = {0};
         rsForEach(gTransformScript, data->children, nullAlloc, &toChild, sizeof(toChild));
     }
 
diff --git a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/test_app.rs b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/test_app.rs
index 997a1a7..d94da52 100644
--- a/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/test_app.rs
+++ b/tests/RenderScriptTests/SceneGraph/src/com/android/testapp/test_app.rs
@@ -41,9 +41,7 @@
     gRotate = 0.0f;
 }
 
-static int pos = 50;
 static float gRotateY = 120.0f;
-static float3 gLookAt = 0;
 static float gZoom = 50.0f;
 static void displayLoading() {
     if (rsIsObject(gRobotTex) && rsIsObject(gRobotMesh)) {
diff --git a/tests/RenderScriptTests/ShadersTest/src/com/android/shaderstest/shaderstest.rs b/tests/RenderScriptTests/ShadersTest/src/com/android/shaderstest/shaderstest.rs
index ae32e3a..735f6b9 100644
--- a/tests/RenderScriptTests/ShadersTest/src/com/android/shaderstest/shaderstest.rs
+++ b/tests/RenderScriptTests/ShadersTest/src/com/android/shaderstest/shaderstest.rs
@@ -131,7 +131,6 @@
     rs_allocation allMeshes = rsGetAllocation(gMeshes);
     int size = rsAllocationGetDimX(allMeshes);
     gLookAt = 0.0f;
-    float minX, minY, minZ, maxX, maxY, maxZ;
     for (int i = 0; i < size; i++) {
         MeshInfo_t *info = (MeshInfo_t*)rsGetElementAt(allMeshes, i);
         rsgDrawMesh(info->mMesh);
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index bbe6860..d551c8e 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -50,9 +50,11 @@
 aaptTests := \
     tests/AaptConfig_test.cpp \
     tests/AaptGroupEntry_test.cpp \
+    tests/Pseudolocales_test.cpp \
     tests/ResourceFilter_test.cpp
 
 aaptCIncludes := \
+    system/core/base/include \
     external/libpng \
     external/zlib
 
@@ -99,7 +101,6 @@
 
 include $(BUILD_HOST_STATIC_LIBRARY)
 
-
 # ==========================================================
 # Build the host executable: aapt
 # ==========================================================
diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp
index 9033cf7..bf31bc1 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -213,16 +213,14 @@
     Vector<StringPool::entry_style_span> spanStack;
     String16 curString;
     String16 rawString;
+    Pseudolocalizer pseudo(pseudolocalize);
     const char* errorMsg;
     int xliffDepth = 0;
     bool firstTime = true;
 
     size_t len;
     ResXMLTree::event_code_t code;
-    // Bracketing if pseudolocalization accented method specified.
-    if (pseudolocalize == PSEUDO_ACCENTED) {
-        curString.append(String16(String8("[")));
-    }
+    curString.append(pseudo.start());
     while ((code=inXml->next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
         if (code == ResXMLTree::TEXT) {
             String16 text(inXml->getText(&len));
@@ -231,18 +229,12 @@
                 if (text.string()[0] == '@') {
                     // If this is a resource reference, don't do the pseudoloc.
                     pseudolocalize = NO_PSEUDOLOCALIZATION;
+                    pseudo.setMethod(pseudolocalize);
+                    curString = String16();
                 }
             }
             if (xliffDepth == 0 && pseudolocalize > 0) {
-                String16 pseudo;
-                if (pseudolocalize == PSEUDO_ACCENTED) {
-                    pseudo = pseudolocalize_string(text);
-                } else if (pseudolocalize == PSEUDO_BIDI) {
-                    pseudo = pseudobidi_string(text);
-                } else {
-                    pseudo = text;
-                }
-                curString.append(pseudo);
+                curString.append(pseudo.text(text));
             } else {
                 if (isFormatted && hasSubstitutionErrors(fileName, inXml, text) != NO_ERROR) {
                     return UNKNOWN_ERROR;
@@ -382,24 +374,7 @@
         }
     }
 
-    // Bracketing if pseudolocalization accented method specified.
-    if (pseudolocalize == PSEUDO_ACCENTED) {
-        const char16_t* str = outString->string();
-        const char16_t* p = str;
-        const char16_t* e = p + outString->size();
-        int words_cnt = 0;
-        while (p < e) {
-            if (isspace(*p)) {
-                words_cnt++;
-            }
-            p++;
-        }
-        unsigned int length = words_cnt > 3 ? outString->size() :
-            outString->size() / 2;
-        curString.append(String16(String8(" ")));
-        curString.append(pseudo_generate_expansion(length));
-        curString.append(String16(String8("]")));
-    }
+    curString.append(pseudo.end());
 
     if (code == ResXMLTree::BAD_DOCUMENT) {
             SourcePos(String8(fileName), inXml->getLineNumber()).error(
diff --git a/tools/aapt/pseudolocalize.cpp b/tools/aapt/pseudolocalize.cpp
index 60aa2b2..c7fee2c 100644
--- a/tools/aapt/pseudolocalize.cpp
+++ b/tools/aapt/pseudolocalize.cpp
@@ -16,6 +16,80 @@
 static const String16 k_placeholder_open = String16("\xc2\xbb");
 static const String16 k_placeholder_close = String16("\xc2\xab");
 
+static const char16_t k_arg_start = '{';
+static const char16_t k_arg_end = '}';
+
+Pseudolocalizer::Pseudolocalizer(PseudolocalizationMethod m)
+    : mImpl(nullptr), mLastDepth(0) {
+  setMethod(m);
+}
+
+void Pseudolocalizer::setMethod(PseudolocalizationMethod m) {
+  if (mImpl) {
+    delete mImpl;
+  }
+  if (m == PSEUDO_ACCENTED) {
+    mImpl = new PseudoMethodAccent();
+  } else if (m == PSEUDO_BIDI) {
+    mImpl = new PseudoMethodBidi();
+  } else {
+    mImpl = new PseudoMethodNone();
+  }
+}
+
+String16 Pseudolocalizer::text(const String16& text) {
+  String16 out;
+  size_t depth = mLastDepth;
+  size_t lastpos, pos;
+  const size_t length= text.size();
+  const char16_t* str = text.string();
+  bool escaped = false;
+  for (lastpos = pos = 0; pos < length; pos++) {
+    char16_t c = str[pos];
+    if (escaped) {
+      escaped = false;
+      continue;
+    }
+    if (c == '\'') {
+      escaped = true;
+      continue;
+    }
+
+    if (c == k_arg_start) {
+      depth++;
+    } else if (c == k_arg_end && depth) {
+      depth--;
+    }
+
+    if (mLastDepth != depth || pos == length - 1) {
+      bool pseudo = ((mLastDepth % 2) == 0);
+      size_t nextpos = pos;
+      if (!pseudo || depth == mLastDepth) {
+        nextpos++;
+      }
+      size_t size = nextpos - lastpos;
+      if (size) {
+        String16 chunk = String16(text, size, lastpos);
+        if (pseudo) {
+          chunk = mImpl->text(chunk);
+        } else if (str[lastpos] == k_arg_start &&
+                   str[nextpos - 1] == k_arg_end) {
+          chunk = mImpl->placeholder(chunk);
+        }
+        out.append(chunk);
+      }
+      if (pseudo && depth < mLastDepth) { // End of message
+        out.append(mImpl->end());
+      } else if (!pseudo && depth > mLastDepth) { // Start of message
+        out.append(mImpl->start());
+      }
+      lastpos = nextpos;
+      mLastDepth = depth;
+    }
+  }
+  return out;
+}
+
 static const char*
 pseudolocalize_char(const char16_t c)
 {
@@ -78,8 +152,7 @@
     }
 }
 
-static bool
-is_possible_normal_placeholder_end(const char16_t c) {
+static bool is_possible_normal_placeholder_end(const char16_t c) {
     switch (c) {
         case 's': return true;
         case 'S': return true;
@@ -106,8 +179,7 @@
     }
 }
 
-String16
-pseudo_generate_expansion(const unsigned int length) {
+static String16 pseudo_generate_expansion(const unsigned int length) {
     String16 result = k_expansion_string;
     const char16_t* s = result.string();
     if (result.size() < length) {
@@ -127,18 +199,47 @@
     return result;
 }
 
+static bool is_space(const char16_t c) {
+  return (c == ' ' || c == '\t' || c == '\n');
+}
+
+String16 PseudoMethodAccent::start() {
+  String16 result;
+  if (mDepth == 0) {
+    result = String16(String8("["));
+  }
+  mWordCount = mLength = 0;
+  mDepth++;
+  return result;
+}
+
+String16 PseudoMethodAccent::end() {
+  String16 result;
+  if (mLength) {
+    result.append(String16(String8(" ")));
+    result.append(pseudo_generate_expansion(
+        mWordCount > 3 ? mLength : mLength / 2));
+  }
+  mWordCount = mLength = 0;
+  mDepth--;
+  if (mDepth == 0) {
+    result.append(String16(String8("]")));
+  }
+  return result;
+}
+
 /**
  * Converts characters so they look like they've been localized.
  *
  * Note: This leaves escape sequences untouched so they can later be
  * processed by ResTable::collectString in the normal way.
  */
-String16
-pseudolocalize_string(const String16& source)
+String16 PseudoMethodAccent::text(const String16& source)
 {
     const char16_t* s = source.string();
     String16 result;
     const size_t I = source.size();
+    bool lastspace = true;
     for (size_t i=0; i<I; i++) {
         char16_t c = s[i];
         if (c == '\\') {
@@ -170,23 +271,24 @@
             }
         } else if (c == '%') {
             // Placeholder syntax, no need to pseudolocalize
-            result += k_placeholder_open;
+            String16 chunk;
             bool end = false;
-            result.append(&c, 1);
+            chunk.append(&c, 1);
             while (!end && i < I) {
                 ++i;
                 c = s[i];
-                result.append(&c, 1);
+                chunk.append(&c, 1);
                 if (is_possible_normal_placeholder_end(c)) {
                     end = true;
                 } else if (c == 't') {
                     ++i;
                     c = s[i];
-                    result.append(&c, 1);
+                    chunk.append(&c, 1);
                     end = true;
                 }
             }
-            result += k_placeholder_close;
+            // Treat chunk as a placeholder unless it ends with %.
+            result += ((c == '%') ? chunk : placeholder(chunk));
         } else if (c == '<' || c == '&') {
             // html syntax, no need to pseudolocalize
             bool tag_closed = false;
@@ -234,35 +336,52 @@
             if (p != NULL) {
                 result += String16(p);
             } else {
+                bool space = is_space(c);
+                if (lastspace && !space) {
+                  mWordCount++;
+                }
+                lastspace = space;
                 result.append(&c, 1);
             }
+            // Count only pseudolocalizable chars and delimiters
+            mLength++;
         }
     }
     return result;
 }
+String16 PseudoMethodAccent::placeholder(const String16& source) {
+  // Surround a placeholder with brackets
+  return k_placeholder_open + source + k_placeholder_close;
+}
 
-String16
-pseudobidi_string(const String16& source)
+String16 PseudoMethodBidi::text(const String16& source)
 {
     const char16_t* s = source.string();
     String16 result;
-    result += k_rlm;
-    result += k_rlo;
+    bool lastspace = true;
+    bool space = true;
     for (size_t i=0; i<source.size(); i++) {
         char16_t c = s[i];
-        switch(c) {
-            case ' ': result += k_pdf;
-                      result += k_rlm;
-                      result.append(&c, 1);
-                      result += k_rlm;
-                      result += k_rlo;
-                      break;
-            default: result.append(&c, 1);
-                     break;
+        space = is_space(c);
+        if (lastspace && !space) {
+          // Word start
+          result += k_rlm + k_rlo;
+        } else if (!lastspace && space) {
+          // Word end
+          result += k_pdf + k_rlm;
         }
+        lastspace = space;
+        result.append(&c, 1);
     }
-    result += k_pdf;
-    result += k_rlm;
+    if (!lastspace) {
+      // End of last word
+      result += k_pdf + k_rlm;
+    }
     return result;
 }
 
+String16 PseudoMethodBidi::placeholder(const String16& source) {
+  // Surround a placeholder with directionality change sequence
+  return k_rlm + k_rlo + source + k_pdf + k_rlm;
+}
+
diff --git a/tools/aapt/pseudolocalize.h b/tools/aapt/pseudolocalize.h
index e6ab18e..71b974b 100644
--- a/tools/aapt/pseudolocalize.h
+++ b/tools/aapt/pseudolocalize.h
@@ -1,18 +1,58 @@
 #ifndef HOST_PSEUDOLOCALIZE_H
 #define HOST_PSEUDOLOCALIZE_H
 
+#include <base/macros.h>
 #include "StringPool.h"
 
-#include <string>
+class PseudoMethodImpl {
+ public:
+  virtual ~PseudoMethodImpl() {}
+  virtual String16 start() { return String16(); }
+  virtual String16 end() { return String16(); }
+  virtual String16 text(const String16& text) = 0;
+  virtual String16 placeholder(const String16& text) = 0;
+};
 
-String16 pseudolocalize_string(const String16& source);
-// Surrounds every word in the sentance with specific characters that makes
-// the word directionality RTL.
-String16 pseudobidi_string(const String16& source);
-// Generates expansion string based on the specified lenght.
-// Generated string could not be shorter that length, but it could be slightly
-// longer.
-String16 pseudo_generate_expansion(const unsigned int length);
+class PseudoMethodNone : public PseudoMethodImpl {
+ public:
+  PseudoMethodNone() {}
+  String16 text(const String16& text) { return text; }
+  String16 placeholder(const String16& text) { return text; }
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PseudoMethodNone);
+};
+
+class PseudoMethodBidi : public PseudoMethodImpl {
+ public:
+  String16 text(const String16& text);
+  String16 placeholder(const String16& text);
+};
+
+class PseudoMethodAccent : public PseudoMethodImpl {
+ public:
+  PseudoMethodAccent() : mDepth(0), mWordCount(0), mLength(0) {}
+  String16 start();
+  String16 end();
+  String16 text(const String16& text);
+  String16 placeholder(const String16& text);
+ private:
+  size_t mDepth;
+  size_t mWordCount;
+  size_t mLength;
+};
+
+class Pseudolocalizer {
+ public:
+  Pseudolocalizer(PseudolocalizationMethod m);
+  ~Pseudolocalizer() { if (mImpl) delete mImpl; }
+  void setMethod(PseudolocalizationMethod m);
+  String16 start() { return mImpl->start(); }
+  String16 end() { return mImpl->end(); }
+  String16 text(const String16& text);
+ private:
+  PseudoMethodImpl *mImpl;
+  size_t mLastDepth;
+};
 
 #endif // HOST_PSEUDOLOCALIZE_H
 
diff --git a/tools/aapt/tests/Pseudolocales_test.cpp b/tools/aapt/tests/Pseudolocales_test.cpp
new file mode 100644
index 0000000..4670e9f
--- /dev/null
+++ b/tools/aapt/tests/Pseudolocales_test.cpp
@@ -0,0 +1,217 @@
+/*
+ * 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.
+ */
+
+#include <androidfw/ResourceTypes.h>
+#include <utils/String8.h>
+#include <gtest/gtest.h>
+
+#include "Bundle.h"
+#include "pseudolocalize.h"
+
+using android::String8;
+
+// In this context, 'Axis' represents a particular field in the configuration,
+// such as language or density.
+
+static void simple_helper(const char* input, const char* expected, PseudolocalizationMethod method) {
+    Pseudolocalizer pseudo(method);
+    String16 result = pseudo.start() + pseudo.text(String16(String8(input))) + pseudo.end();
+    //std::cout << String8(result).string() << std::endl;
+    ASSERT_EQ(String8(expected), String8(result));
+}
+
+static void compound_helper(const char* in1, const char* in2, const char *in3,
+                            const char* expected, PseudolocalizationMethod method) {
+    Pseudolocalizer pseudo(method);
+    String16 result = pseudo.start() + \
+                      pseudo.text(String16(String8(in1))) + \
+                      pseudo.text(String16(String8(in2))) + \
+                      pseudo.text(String16(String8(in3))) + \
+                      pseudo.end();
+    ASSERT_EQ(String8(expected), String8(result));
+}
+
+TEST(Pseudolocales, NoPseudolocalization) {
+  simple_helper("", "", NO_PSEUDOLOCALIZATION);
+  simple_helper("Hello, world", "Hello, world", NO_PSEUDOLOCALIZATION);
+
+  compound_helper("Hello,", " world", "",
+                  "Hello, world", NO_PSEUDOLOCALIZATION);
+}
+
+TEST(Pseudolocales, PlaintextAccent) {
+  simple_helper("", "[]", PSEUDO_ACCENTED);
+  simple_helper("Hello, world",
+                "[Ĥéļļö, ŵöŕļð one two]", PSEUDO_ACCENTED);
+
+  simple_helper("Hello, %1d",
+                "[Ĥéļļö, »%1d« one two]", PSEUDO_ACCENTED);
+
+  simple_helper("Battery %1d%%",
+                "[βåţţéŕý »%1d«%% one two]", PSEUDO_ACCENTED);
+
+  compound_helper("", "", "", "[]", PSEUDO_ACCENTED);
+  compound_helper("Hello,", " world", "",
+                  "[Ĥéļļö, ŵöŕļð one two]", PSEUDO_ACCENTED);
+}
+
+TEST(Pseudolocales, PlaintextBidi) {
+  simple_helper("", "", PSEUDO_BIDI);
+  simple_helper("word",
+                "\xe2\x80\x8f\xE2\x80\xaeword\xE2\x80\xac\xe2\x80\x8f",
+                PSEUDO_BIDI);
+  simple_helper("  word  ",
+                "  \xe2\x80\x8f\xE2\x80\xaeword\xE2\x80\xac\xe2\x80\x8f  ",
+                PSEUDO_BIDI);
+  simple_helper("  word  ",
+                "  \xe2\x80\x8f\xE2\x80\xaeword\xE2\x80\xac\xe2\x80\x8f  ",
+                PSEUDO_BIDI);
+  simple_helper("hello\n  world\n",
+                "\xe2\x80\x8f\xE2\x80\xaehello\xE2\x80\xac\xe2\x80\x8f\n" \
+                "  \xe2\x80\x8f\xE2\x80\xaeworld\xE2\x80\xac\xe2\x80\x8f\n",
+                PSEUDO_BIDI);
+  compound_helper("hello", "\n ", " world\n",
+                "\xe2\x80\x8f\xE2\x80\xaehello\xE2\x80\xac\xe2\x80\x8f\n" \
+                "  \xe2\x80\x8f\xE2\x80\xaeworld\xE2\x80\xac\xe2\x80\x8f\n",
+                PSEUDO_BIDI);
+}
+
+TEST(Pseudolocales, SimpleICU) {
+  // Single-fragment messages
+  simple_helper("{placeholder}", "[»{placeholder}«]", PSEUDO_ACCENTED);
+  simple_helper("{USER} is offline",
+              "[»{USER}« îš öƒƒļîñé one two]", PSEUDO_ACCENTED);
+  simple_helper("Copy from {path1} to {path2}",
+              "[Çöþý ƒŕöḿ »{path1}« ţö »{path2}« one two three]", PSEUDO_ACCENTED);
+  simple_helper("Today is {1,date} {1,time}",
+              "[Ţöðåý îš »{1,date}« »{1,time}« one two]", PSEUDO_ACCENTED);
+
+  // Multi-fragment messages
+  compound_helper("{USER}", " ", "is offline",
+                  "[»{USER}« îš öƒƒļîñé one two]",
+                  PSEUDO_ACCENTED);
+  compound_helper("Copy from ", "{path1}", " to {path2}",
+                  "[Çöþý ƒŕöḿ »{path1}« ţö »{path2}« one two three]",
+                  PSEUDO_ACCENTED);
+}
+
+TEST(Pseudolocales, ICUBidi) {
+  // Single-fragment messages
+  simple_helper("{placeholder}",
+                "\xe2\x80\x8f\xE2\x80\xae{placeholder}\xE2\x80\xac\xe2\x80\x8f",
+                PSEUDO_BIDI);
+  simple_helper(
+      "{COUNT, plural, one {one} other {other}}",
+      "{COUNT, plural, " \
+          "one {\xe2\x80\x8f\xE2\x80\xaeone\xE2\x80\xac\xe2\x80\x8f} " \
+        "other {\xe2\x80\x8f\xE2\x80\xaeother\xE2\x80\xac\xe2\x80\x8f}}",
+      PSEUDO_BIDI
+  );
+}
+
+TEST(Pseudolocales, Escaping) {
+  // Single-fragment messages
+  simple_helper("'{USER'} is offline",
+                "['{ÛŠÉŔ'} îš öƒƒļîñé one two three]", PSEUDO_ACCENTED);
+
+  // Multi-fragment messages
+  compound_helper("'{USER}", " ", "''is offline",
+                  "['{ÛŠÉŔ} ''îš öƒƒļîñé one two three]", PSEUDO_ACCENTED);
+}
+
+TEST(Pseudolocales, PluralsAndSelects) {
+  simple_helper(
+      "{COUNT, plural, one {Delete a file} other {Delete {COUNT} files}}",
+      "[{COUNT, plural, one {Ðéļéţé å ƒîļé one two} " \
+                     "other {Ðéļéţé »{COUNT}« ƒîļéš one two}}]",
+      PSEUDO_ACCENTED
+  );
+  simple_helper(
+      "Distance is {COUNT, plural, one {# mile} other {# miles}}",
+      "[Ðîšţåñçé îš {COUNT, plural, one {# ḿîļé one two} " \
+                                 "other {# ḿîļéš one two}}]",
+      PSEUDO_ACCENTED
+  );
+  simple_helper(
+      "{1, select, female {{1} added you} " \
+        "male {{1} added you} other {{1} added you}}",
+      "[{1, select, female {»{1}« åððéð ýöû one two} " \
+        "male {»{1}« åððéð ýöû one two} other {»{1}« åððéð ýöû one two}}]",
+      PSEUDO_ACCENTED
+  );
+
+  compound_helper(
+      "{COUNT, plural, one {Delete a file} " \
+        "other {Delete ", "{COUNT}", " files}}",
+      "[{COUNT, plural, one {Ðéļéţé å ƒîļé one two} " \
+        "other {Ðéļéţé »{COUNT}« ƒîļéš one two}}]",
+      PSEUDO_ACCENTED
+  );
+}
+
+TEST(Pseudolocales, NestedICU) {
+  simple_helper(
+      "{person, select, " \
+        "female {" \
+          "{num_circles, plural," \
+            "=0{{person} didn't add you to any of her circles.}" \
+            "=1{{person} added you to one of her circles.}" \
+            "other{{person} added you to her # circles.}}}" \
+        "male {" \
+          "{num_circles, plural," \
+            "=0{{person} didn't add you to any of his circles.}" \
+            "=1{{person} added you to one of his circles.}" \
+            "other{{person} added you to his # circles.}}}" \
+        "other {" \
+          "{num_circles, plural," \
+            "=0{{person} didn't add you to any of their circles.}" \
+            "=1{{person} added you to one of their circles.}" \
+            "other{{person} added you to their # circles.}}}}",
+      "[{person, select, " \
+        "female {" \
+          "{num_circles, plural," \
+            "=0{»{person}« ðîðñ'ţ åðð ýöû ţö åñý öƒ ĥéŕ çîŕçļéš." \
+              " one two three four five}" \
+            "=1{»{person}« åððéð ýöû ţö öñé öƒ ĥéŕ çîŕçļéš." \
+              " one two three four}" \
+            "other{»{person}« åððéð ýöû ţö ĥéŕ # çîŕçļéš." \
+              " one two three four}}}" \
+        "male {" \
+          "{num_circles, plural," \
+            "=0{»{person}« ðîðñ'ţ åðð ýöû ţö åñý öƒ ĥîš çîŕçļéš." \
+              " one two three four five}" \
+            "=1{»{person}« åððéð ýöû ţö öñé öƒ ĥîš çîŕçļéš." \
+              " one two three four}" \
+            "other{»{person}« åððéð ýöû ţö ĥîš # çîŕçļéš." \
+              " one two three four}}}" \
+        "other {{num_circles, plural," \
+          "=0{»{person}« ðîðñ'ţ åðð ýöû ţö åñý öƒ ţĥéîŕ çîŕçļéš." \
+            " one two three four five}" \
+          "=1{»{person}« åððéð ýöû ţö öñé öƒ ţĥéîŕ çîŕçļéš." \
+            " one two three four}" \
+          "other{»{person}« åððéð ýöû ţö ţĥéîŕ # çîŕçļéš." \
+            " one two three four}}}}]",
+      PSEUDO_ACCENTED
+  );
+}
+
+TEST(Pseudolocales, RedefineMethod) {
+  Pseudolocalizer pseudo(PSEUDO_ACCENTED);
+  String16 result = pseudo.text(String16(String8("Hello, ")));
+  pseudo.setMethod(NO_PSEUDOLOCALIZATION);
+  result.append(pseudo.text(String16(String8("world!"))));
+  ASSERT_EQ(String8("Ĥéļļö, world!"), String8(result));
+}