Merge "Prevent Lockscreen album art from activating FLAG_KEEP_SCREEN_ON"
diff --git a/cmds/app_process/Android.mk b/cmds/app_process/Android.mk
index b9afe40..cb7e1a0 100644
--- a/cmds/app_process/Android.mk
+++ b/cmds/app_process/Android.mk
@@ -1,4 +1,6 @@
 LOCAL_PATH:= $(call my-dir)
+
+# 32-bit app_process
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
@@ -12,9 +14,29 @@
 	libandroid_runtime
 
 LOCAL_MODULE:= app_process
-
+LOCAL_32_BIT_ONLY := true
 include $(BUILD_EXECUTABLE)
 
+ifeq ($(TARGET_IS_64_BIT),true)
+
+# 64-bit app_process64
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	app_main.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+	libutils \
+	liblog \
+	libbinder \
+	libandroid_runtime
+
+LOCAL_MODULE:= app_process64
+LOCAL_NO_2ND_ARCH := true
+include $(BUILD_EXECUTABLE)
+
+endif # TARGET_IS_64_BIT
 
 # Build a variant of app_process binary linked with ASan runtime.
 # ARM-only at the moment.
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index d6db8c2..10ef535 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -816,7 +816,7 @@
     }
 
     /**
-     * Return the LoaderManager for this fragment, creating it if needed.
+     * Return the LoaderManager for this activity, creating it if needed.
      */
     public LoaderManager getLoaderManager() {
         if (mLoaderManager != null) {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d3080e5..b103e71 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -68,6 +68,7 @@
 import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.util.AndroidRuntimeException;
 import android.util.ArrayMap;
 import android.util.DisplayMetrics;
@@ -106,6 +107,7 @@
 import java.lang.ref.WeakReference;
 import java.net.InetAddress;
 import java.security.Security;
+import java.text.DateFormat;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
@@ -742,8 +744,42 @@
 
             setCoreSettings(coreSettings);
 
-            // Tell the VMRuntime about the application.
-            VMRuntime.registerAppInfo(appInfo.dataDir, appInfo.processName);
+            /*
+             * Two possible indications that this package could be
+             * sharing its runtime with other packages:
+             *
+             * 1.) the sharedUserId attribute is set in the manifest,
+             *     indicating a request to share a VM with other
+             *     packages with the same sharedUserId.
+             *
+             * 2.) the application element of the manifest has an
+             *     attribute specifying a non-default process name,
+             *     indicating the desire to run in another packages VM.
+             *
+             * If sharing is enabled we do not have a unique application
+             * in a process and therefore cannot rely on the package
+             * name inside the runtime.
+             */
+            IPackageManager pm = getPackageManager();
+            android.content.pm.PackageInfo pi = null;
+            try {
+                pi = pm.getPackageInfo(appInfo.packageName, 0, UserHandle.myUserId());
+            } catch (RemoteException e) {
+            }
+            if (pi != null) {
+                boolean sharedUserIdSet = (pi.sharedUserId != null);
+                boolean processNameNotDefault =
+                (pi.applicationInfo != null &&
+                 !appInfo.packageName.equals(pi.applicationInfo.processName));
+                boolean sharable = (sharedUserIdSet || processNameNotDefault);
+
+                // Tell the VMRuntime about the application, unless it is shared
+                // inside a process.
+                if (!sharable) {
+                    VMRuntime.registerAppInfo(appInfo.packageName, appInfo.dataDir,
+                                            appInfo.processName);
+                }
+            }
 
             AppBindData data = new AppBindData();
             data.processName = processName;
@@ -1095,6 +1131,11 @@
         public void scheduleInstallProvider(ProviderInfo provider) {
             sendMessage(H.INSTALL_PROVIDER, provider);
         }
+
+        @Override
+        public final void updateTimePrefs(boolean is24Hour) {
+            DateFormat.set24HourTimePref(is24Hour);
+        }
     }
 
     private class H extends Handler {
@@ -1144,6 +1185,7 @@
         public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143;
         public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144;
         public static final int INSTALL_PROVIDER        = 145;
+
         String codeToString(int code) {
             if (DEBUG_MESSAGES) {
                 switch (code) {
@@ -4189,6 +4231,11 @@
                 Log.e(TAG, "Unable to setupGraphicsSupport due to missing cache directory");
             }
         }
+
+
+        final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24));
+        DateFormat.set24HourTimePref(is24Hr);
+
         /**
          * For system applications on userdebug/eng builds, log stack
          * traces of disk and network access to dropbox for analysis.
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 347d43f..cb453e2 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -627,6 +627,15 @@
             reply.writeNoException();
             return true;
         }
+
+        case UPDATE_TIME_PREFS_TRANSACTION:
+        {
+            data.enforceInterface(IApplicationThread.descriptor);
+            byte is24Hour = data.readByte();
+            updateTimePrefs(is24Hour == (byte) 1);
+            reply.writeNoException();
+            return true;
+        }
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -1266,4 +1275,13 @@
         mRemote.transact(SCHEDULE_INSTALL_PROVIDER_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
         data.recycle();
     }
+
+    @Override
+    public void updateTimePrefs(boolean is24Hour) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        data.writeInterfaceToken(IApplicationThread.descriptor);
+        data.writeByte(is24Hour ? (byte) 1 : (byte) 0);
+        mRemote.transact(UPDATE_TIME_PREFS_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
+        data.recycle();
+    }
 }
diff --git a/core/java/android/app/IAlarmManager.aidl b/core/java/android/app/IAlarmManager.aidl
index 8476609..ef9f26e 100644
--- a/core/java/android/app/IAlarmManager.aidl
+++ b/core/java/android/app/IAlarmManager.aidl
@@ -28,7 +28,7 @@
 	/** windowLength == 0 means exact; windowLength < 0 means the let the OS decide */
     void set(int type, long triggerAtTime, long windowLength,
             long interval, in PendingIntent operation, in WorkSource workSource);
-    void setTime(long millis);
+    boolean setTime(long millis);
     void setTimeZone(String zone);
     void remove(in PendingIntent operation);
 }
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index d0cc1bb..3aceff9 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -138,6 +138,7 @@
             throws RemoteException;
     void setProcessState(int state) throws RemoteException;
     void scheduleInstallProvider(ProviderInfo provider) throws RemoteException;
+    void updateTimePrefs(boolean is24Hour) throws RemoteException;
 
     String descriptor = "android.app.IApplicationThread";
 
@@ -191,4 +192,5 @@
     int SCHEDULE_TRANSLUCENT_CONVERSION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+48;
     int SET_PROCESS_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+49;
     int SCHEDULE_INSTALL_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+50;
+    int UPDATE_TIME_PREFS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+51;
 }
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index ddde3fb..44831fc 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -987,7 +987,7 @@
      * Implement this to handle requests to delete one or more rows.
      * The implementation should apply the selection clause when performing
      * deletion, allowing the operation to affect multiple rows in a directory.
-     * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyDelete()}
+     * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}
      * after deleting.
      * This method can be called from multiple threads, as described in
      * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index a289649..2e2d4b8 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3331,6 +3331,15 @@
     public static final String EXTRA_SHUTDOWN_USERSPACE_ONLY
             = "android.intent.extra.SHUTDOWN_USERSPACE_ONLY";
 
+    /**
+     * Optional boolean extra for {@link #ACTION_TIME_CHANGED} that indicates the
+     * user has set their time format preferences to the 24 hour format.
+     *
+     * @hide for internal use only.
+     */
+    public static final String EXTRA_TIME_PREF_24_HOUR_FORMAT =
+            "android.intent.extra.TIME_PREF_24_HOUR_FORMAT";
+
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Intent flags (see mFlags variable).
diff --git a/core/java/android/content/Loader.java b/core/java/android/content/Loader.java
index 911e49c..a045b3a 100644
--- a/core/java/android/content/Loader.java
+++ b/core/java/android/content/Loader.java
@@ -24,7 +24,7 @@
 import java.io.PrintWriter;
 
 /**
- * An abstract class that performs asynchronous loading of data. While Loaders are active
+ * A class that performs asynchronous loading of data. While Loaders are active
  * they should monitor the source of their data and deliver new results when the contents
  * change.  See {@link android.app.LoaderManager} for more detail.
  *
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 418bdda..9ce17e4 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -537,7 +537,7 @@
     
     public final class AssetInputStream extends InputStream {
         public final int getAssetInt() {
-            return (int) mAsset;
+            throw new UnsupportedOperationException();
         }
         /**
          * @hide
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 7fc364f..3d9daca 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1569,10 +1569,7 @@
 
             String locale = null;
             if (mConfiguration.locale != null) {
-                locale = mConfiguration.locale.getLanguage();
-                if (mConfiguration.locale.getCountry() != null) {
-                    locale += "-" + mConfiguration.locale.getCountry();
-                }
+                locale = mConfiguration.locale.toLanguageTag();
             }
             int width, height;
             if (mMetrics.widthPixels >= mMetrics.heightPixels) {
diff --git a/core/java/android/debug/JNITest.java b/core/java/android/debug/JNITest.java
deleted file mode 100644
index 2ce374a..0000000
--- a/core/java/android/debug/JNITest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.debug;
-
-/**
- * Simple JNI verification test.
- */
-public class JNITest {
-
-    public JNITest() {
-    }
-
-    public int test(int intArg, double doubleArg, String stringArg) {
-        int[] intArray = { 42, 53, 65, 127 };
-
-        return part1(intArg, doubleArg, stringArg, intArray);
-    }
-
-    private native int part1(int intArg, double doubleArg, String stringArg,
-        int[] arrayArg);
-
-    private int part2(double doubleArg, int fromArray, String stringArg) {
-        int result;
-
-        System.out.println(stringArg + " : " + (float) doubleArg + " : " +
-            fromArray);
-        result = part3(stringArg);
-
-        return result + 6;
-    }
-
-    private static native int part3(String stringArg);
-}
-
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index b931313..ac9189d 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -1359,7 +1359,7 @@
         float q2 = rotationVector[1];
         float q3 = rotationVector[2];
 
-        if (rotationVector.length == 4) {
+        if (rotationVector.length >= 4) {
             q0 = rotationVector[3];
         } else {
             q0 = 1 - q1*q1 - q2*q2 - q3*q3;
@@ -1416,7 +1416,7 @@
      *  @param Q an array of floats in which to store the computed quaternion
      */
     public static void getQuaternionFromVector(float[] Q, float[] rv) {
-        if (rv.length == 4) {
+        if (rv.length >= 4) {
             Q[0] = rv[3];
         } else {
             Q[0] = 1 - rv[0]*rv[0] - rv[1]*rv[1] - rv[2]*rv[2];
diff --git a/core/java/android/net/LocalSocketImpl.java b/core/java/android/net/LocalSocketImpl.java
index b2ee50a..119e533 100644
--- a/core/java/android/net/LocalSocketImpl.java
+++ b/core/java/android/net/LocalSocketImpl.java
@@ -326,6 +326,7 @@
         }
 
         s.fd = accept(fd, s);
+        s.mFdCreatedInternally = true;
     }
 
     /**
@@ -536,4 +537,3 @@
         close();
     }
 }
-
diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java
index 9c3e405..7b2c623 100644
--- a/core/java/android/net/nsd/NsdManager.java
+++ b/core/java/android/net/nsd/NsdManager.java
@@ -301,27 +301,36 @@
 
         @Override
         public void handleMessage(Message message) {
-            Object listener = getListener(message.arg2);
-            boolean listenerRemove = true;
             switch (message.what) {
                 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
                     mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
-                    break;
+                    return;
                 case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
                     mConnected.countDown();
-                    break;
+                    return;
                 case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
                     Log.e(TAG, "Channel lost");
+                    return;
+                default:
                     break;
+            }
+            Object listener = getListener(message.arg2);
+            if (listener == null) {
+                Log.d(TAG, "Stale key " + message.arg2);
+                return;
+            }
+            boolean listenerRemove = true;
+            NsdServiceInfo ns = getNsdService(message.arg2);
+            switch (message.what) {
                 case DISCOVER_SERVICES_STARTED:
-                    String s = ((NsdServiceInfo) message.obj).getServiceType();
+                    String s = getNsdServiceInfoType((NsdServiceInfo) message.obj);
                     ((DiscoveryListener) listener).onDiscoveryStarted(s);
                     // Keep listener until stop discovery
                     listenerRemove = false;
                     break;
                 case DISCOVER_SERVICES_FAILED:
-                    ((DiscoveryListener) listener).onStartDiscoveryFailed(
-                            getNsdService(message.arg2).getServiceType(), message.arg1);
+                    ((DiscoveryListener) listener).onStartDiscoveryFailed(getNsdServiceInfoType(ns),
+                            message.arg1);
                     break;
                 case SERVICE_FOUND:
                     ((DiscoveryListener) listener).onServiceFound((NsdServiceInfo) message.obj);
@@ -334,16 +343,14 @@
                     listenerRemove = false;
                     break;
                 case STOP_DISCOVERY_FAILED:
-                    ((DiscoveryListener) listener).onStopDiscoveryFailed(
-                            getNsdService(message.arg2).getServiceType(), message.arg1);
+                    ((DiscoveryListener) listener).onStopDiscoveryFailed(getNsdServiceInfoType(ns),
+                            message.arg1);
                     break;
                 case STOP_DISCOVERY_SUCCEEDED:
-                    ((DiscoveryListener) listener).onDiscoveryStopped(
-                            getNsdService(message.arg2).getServiceType());
+                    ((DiscoveryListener) listener).onDiscoveryStopped(getNsdServiceInfoType(ns));
                     break;
                 case REGISTER_SERVICE_FAILED:
-                    ((RegistrationListener) listener).onRegistrationFailed(
-                            getNsdService(message.arg2), message.arg1);
+                    ((RegistrationListener) listener).onRegistrationFailed(ns, message.arg1);
                     break;
                 case REGISTER_SERVICE_SUCCEEDED:
                     ((RegistrationListener) listener).onServiceRegistered(
@@ -352,16 +359,13 @@
                     listenerRemove = false;
                     break;
                 case UNREGISTER_SERVICE_FAILED:
-                    ((RegistrationListener) listener).onUnregistrationFailed(
-                            getNsdService(message.arg2), message.arg1);
+                    ((RegistrationListener) listener).onUnregistrationFailed(ns, message.arg1);
                     break;
                 case UNREGISTER_SERVICE_SUCCEEDED:
-                    ((RegistrationListener) listener).onServiceUnregistered(
-                            getNsdService(message.arg2));
+                    ((RegistrationListener) listener).onServiceUnregistered(ns);
                     break;
                 case RESOLVE_SERVICE_FAILED:
-                    ((ResolveListener) listener).onResolveFailed(
-                            getNsdService(message.arg2), message.arg1);
+                    ((ResolveListener) listener).onResolveFailed(ns, message.arg1);
                     break;
                 case RESOLVE_SERVICE_SUCCEEDED:
                     ((ResolveListener) listener).onServiceResolved((NsdServiceInfo) message.obj);
@@ -421,6 +425,11 @@
     }
 
 
+    private String getNsdServiceInfoType(NsdServiceInfo s) {
+        if (s == null) return "?";
+        return s.getServiceType();
+    }
+
     /**
      * Initialize AsyncChannel
      */
diff --git a/core/java/android/nfc/tech/Ndef.java b/core/java/android/nfc/tech/Ndef.java
index 64aa2996..f16dc3b 100644
--- a/core/java/android/nfc/tech/Ndef.java
+++ b/core/java/android/nfc/tech/Ndef.java
@@ -278,6 +278,8 @@
                     throw new TagLostException();
                 }
                 return msg;
+            } else if (!tagService.isPresent(serviceHandle)) {
+                throw new TagLostException();
             } else {
                 return null;
             }
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 3470790..7425f67 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -1459,10 +1459,11 @@
     }
 
     /**
-     * Use this function for customized exception handling.
-     * customized method call this method for all unknown case
-     * @param code exception code
-     * @param msg exception message
+     * Throw an exception with the given message. Not intended for use
+     * outside the Parcel class.
+     *
+     * @param code Used to determine which exception class to throw.
+     * @param msg The exception message.
      */
     public final void readException(int code, String msg) {
         switch (code) {
diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java
index 729c64b..672df6d 100644
--- a/core/java/android/os/SystemClock.java
+++ b/core/java/android/os/SystemClock.java
@@ -16,6 +16,9 @@
 
 package android.os;
 
+import android.app.IAlarmManager;
+import android.content.Context;
+import android.util.Slog;
 
 /**
  * Core timekeeping facilities.
@@ -89,6 +92,8 @@
  * </ul>
  */
 public final class SystemClock {
+    private static final String TAG = "SystemClock";
+
     /**
      * This class is uninstantiable.
      */
@@ -134,7 +139,23 @@
      *
      * @return if the clock was successfully set to the specified time.
      */
-    native public static boolean setCurrentTimeMillis(long millis);
+    public static boolean setCurrentTimeMillis(long millis) {
+        IBinder b = ServiceManager.getService(Context.ALARM_SERVICE);
+        IAlarmManager mgr = IAlarmManager.Stub.asInterface(b);
+        if (mgr == null) {
+            return false;
+        }
+
+        try {
+            return mgr.setTime(millis);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Unable to set RTC", e);
+        } catch (SecurityException e) {
+            Slog.e(TAG, "Unable to set RTC", e);
+        }
+
+        return false;
+    }
 
     /**
      * Returns milliseconds since boot, not counting time spent in deep sleep.
diff --git a/core/java/android/util/JsonReader.java b/core/java/android/util/JsonReader.java
index f2a86c9..7d1c6c4 100644
--- a/core/java/android/util/JsonReader.java
+++ b/core/java/android/util/JsonReader.java
@@ -546,6 +546,9 @@
     public void skipValue() throws IOException {
         skipping = true;
         try {
+            if (!hasNext() || peek() == JsonToken.END_DOCUMENT) {
+                throw new IllegalStateException("No element left to skip");
+            }
             int count = 0;
             do {
                 JsonToken token = advance();
diff --git a/core/java/android/util/Patterns.java b/core/java/android/util/Patterns.java
index 9522112..0f8da44 100644
--- a/core/java/android/util/Patterns.java
+++ b/core/java/android/util/Patterns.java
@@ -191,8 +191,6 @@
         for (int i = 1; i <= numGroups; i++) {
             String s = matcher.group(i);
 
-            System.err.println("Group(" + i + ") : " + s);
-
             if (s != null) {
                 b.append(s);
             }
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 6a15fa6..d533060 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -392,11 +392,11 @@
     // Atlas
     ///////////////////////////////////////////////////////////////////////////
 
-    static void initAtlas(GraphicBuffer buffer, int[] map) {
+    static void initAtlas(GraphicBuffer buffer, long[] map) {
         nInitAtlas(buffer, map, map.length);
     }
 
-    private static native void nInitAtlas(GraphicBuffer buffer, int[] map, int count);
+    private static native void nInitAtlas(GraphicBuffer buffer, long[] map, int count);
 
     ///////////////////////////////////////////////////////////////////////////
     // Display list
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 3781bdb..f09a111 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -1981,7 +1981,7 @@
                 if (atlas.isCompatible(android.os.Process.myPpid())) {
                     GraphicBuffer buffer = atlas.getBuffer();
                     if (buffer != null) {
-                        int[] map = atlas.getMap();
+                        long[] map = atlas.getMap();
                         if (map != null) {
                             GLES20Canvas.initAtlas(buffer, map);
                         }
diff --git a/core/java/android/view/IAssetAtlas.aidl b/core/java/android/view/IAssetAtlas.aidl
index 5f1e238..edce059 100644
--- a/core/java/android/view/IAssetAtlas.aidl
+++ b/core/java/android/view/IAssetAtlas.aidl
@@ -45,10 +45,10 @@
      * if the atlas is not available yet.
      *
      * Each bitmap is represented by several entries in the array:
-     * int0: SkBitmap*, the native bitmap object
-     * int1: x position
-     * int2: y position
-     * int3: rotated, 1 if the bitmap must be rotated, 0 otherwise
+     * long0: SkBitmap*, the native bitmap object
+     * long1: x position
+     * long2: y position
+     * long3: rotated, 1 if the bitmap must be rotated, 0 otherwise
      */
-    int[] getMap();
+    long[] getMap();
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b0bae46..bdf4141 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10098,7 +10098,7 @@
      * by the layout system and should not generally be called otherwise, because the property
      * may be changed at any time by the layout.
      *
-     * @param left The bottom of this view, in pixels.
+     * @param left The left of this view, in pixels.
      */
     public final void setLeft(int left) {
         if (left != mLeft) {
@@ -10165,7 +10165,7 @@
      * by the layout system and should not generally be called otherwise, because the property
      * may be changed at any time by the layout.
      *
-     * @param right The bottom of this view, in pixels.
+     * @param right The right of this view, in pixels.
      */
     public final void setRight(int right) {
         if (right != mRight) {
@@ -11838,7 +11838,7 @@
     }
 
     /**
-     * <p>Compute the vertical extent of the horizontal scrollbar's thumb
+     * <p>Compute the vertical extent of the vertical scrollbar's thumb
      * within the vertical range. This value is used to compute the length
      * of the thumb within the scrollbar's track.</p>
      *
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 7674837..fe2fc96 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -292,7 +292,7 @@
         // The extra space for the thumb to move on the track
         available += mThumbOffset * 2;
 
-        int thumbPos = (int) (scale * available);
+        int thumbPos = (int) (scale * available + 0.5f);
 
         int topBound, bottomBound;
         if (gap == Integer.MIN_VALUE) {
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index a5fad60..a06344f 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -663,7 +663,7 @@
 
     /**
      * When the current adapter is empty, the AdapterView can display a special view
-     * call the empty view. The empty view is used to provide feedback to the user
+     * called the empty view. The empty view is used to provide feedback to the user
      * that no data is available in this AdapterView.
      *
      * @return The view to show if the adapter is empty.
diff --git a/core/java/com/android/internal/util/FileRotator.java b/core/java/com/android/internal/util/FileRotator.java
index 26235f1..71550be 100644
--- a/core/java/com/android/internal/util/FileRotator.java
+++ b/core/java/com/android/internal/util/FileRotator.java
@@ -336,7 +336,12 @@
         final long deleteBefore = currentTimeMillis - mDeleteAgeMillis;
 
         final FileInfo info = new FileInfo(mPrefix);
-        for (String name : mBasePath.list()) {
+        String[] baseFiles = mBasePath.list();
+        if (baseFiles == null) {
+            return;
+        }
+
+        for (String name : baseFiles) {
             if (!info.parse(name)) continue;
 
             if (info.isActive()) {
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 2e0acb1..ac70738 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -134,7 +134,6 @@
 	android_hardware_UsbDevice.cpp \
 	android_hardware_UsbDeviceConnection.cpp \
 	android_hardware_UsbRequest.cpp \
-	android_debug_JNITest.cpp \
 	android_util_FileObserver.cpp \
 	android/opengl/poly_clip.cpp.arm \
 	android/opengl/util.cpp.arm \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 97ea5e6..649968e 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -131,7 +131,6 @@
 extern int register_android_database_SQLiteConnection(JNIEnv* env);
 extern int register_android_database_SQLiteGlobal(JNIEnv* env);
 extern int register_android_database_SQLiteDebug(JNIEnv* env);
-extern int register_android_debug_JNITest(JNIEnv* env);
 extern int register_android_nio_utils(JNIEnv* env);
 extern int register_android_text_format_Time(JNIEnv* env);
 extern int register_android_os_Debug(JNIEnv* env);
@@ -396,16 +395,16 @@
  *
  * This will cut up "extraOptsBuf" as we chop it into individual options.
  *
+ * If "quotingArg" is non-null, it is passed before each extra option in mOptions.
+ *
  * Adds the strings, if any, to mOptions.
  */
-void AndroidRuntime::parseExtraOpts(char* extraOptsBuf)
+void AndroidRuntime::parseExtraOpts(char* extraOptsBuf, const char* quotingArg)
 {
     JavaVMOption opt;
-    char* start;
-    char* end;
-
     memset(&opt, 0, sizeof(opt));
-    start = extraOptsBuf;
+    char* start = extraOptsBuf;
+    char* end = NULL;
     while (*start != '\0') {
         while (*start == ' ')                   /* skip leading whitespace */
             start++;
@@ -419,6 +418,11 @@
             *end++ = '\0';          /* mark end, advance to indicate more */
 
         opt.optionString = start;
+        if (quotingArg != NULL) {
+            JavaVMOption quotingOpt;
+            quotingOpt.optionString = quotingArg;
+            mOptions.add(quotingOpt);
+        }
         mOptions.add(opt);
         start = end;
     }
@@ -430,6 +434,14 @@
  * Various arguments, most determined by system properties, are passed in.
  * The "mOptions" vector is updated.
  *
+ * CAUTION: when adding options in here, be careful not to put the
+ * char buffer inside a nested scope.  Adding the buffer to the
+ * options using mOptions.add() does not copy the buffer, so if the
+ * buffer goes out of scope the option may be overwritten.  It's best
+ * to put the buffer at the top of the function so that it is more
+ * unlikely that someone will surround it in a scope at a later time
+ * and thus introduce a bug.
+ *
  * Returns 0 on success.
  */
 int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
@@ -450,6 +462,9 @@
     char gctypeOptsBuf[sizeof("-Xgc:")-1 + PROPERTY_VALUE_MAX];
     char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX];
     char jitcodecachesizeOptsBuf[sizeof("-Xjitcodecachesize:")-1 + PROPERTY_VALUE_MAX];
+    char dalvikVmLibBuf[PROPERTY_VALUE_MAX];
+    char dex2oatFlagsBuf[PROPERTY_VALUE_MAX];
+    char dex2oatImageFlagsBuf[PROPERTY_VALUE_MAX];
     char extraOptsBuf[PROPERTY_VALUE_MAX];
     char* stackTraceFile = NULL;
     bool checkJni = false;
@@ -461,7 +476,15 @@
       kEMIntFast,
       kEMJitCompiler,
     } executionMode = kEMDefault;
-
+    char profile_period[sizeof("-Xprofile-period:") + PROPERTY_VALUE_MAX];
+    char profile_duration[sizeof("-Xprofile-duration:") + PROPERTY_VALUE_MAX];
+    char profile_interval[sizeof("-Xprofile-interval:") + PROPERTY_VALUE_MAX];
+    char profile_backoff[sizeof("-Xprofile-backoff:") + PROPERTY_VALUE_MAX];
+    char langOption[sizeof("-Duser.language=") + 3];
+    char regionOption[sizeof("-Duser.region=") + 3];
+    char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:") + sizeof(propBuf)];
+    char jitOpBuf[sizeof("-Xjitop:") + PROPERTY_VALUE_MAX];
+    char jitMethodBuf[sizeof("-Xjitmethod:") + PROPERTY_VALUE_MAX];
 
     property_get("dalvik.vm.checkjni", propBuf, "");
     if (strcmp(propBuf, "true") == 0) {
@@ -662,7 +685,6 @@
         //mOptions.add(opt);
     }
 
-    char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:") + sizeof(propBuf)];
     property_get("dalvik.vm.lockprof.threshold", propBuf, "");
     if (strlen(propBuf) > 0) {
       strcpy(lockProfThresholdBuf, "-Xlockprofthreshold:");
@@ -672,7 +694,6 @@
     }
 
     /* Force interpreter-only mode for selected opcodes. Eg "1-0a,3c,f1-ff" */
-    char jitOpBuf[sizeof("-Xjitop:") + PROPERTY_VALUE_MAX];
     property_get("dalvik.vm.jit.op", propBuf, "");
     if (strlen(propBuf) > 0) {
         strcpy(jitOpBuf, "-Xjitop:");
@@ -682,7 +703,6 @@
     }
 
     /* Force interpreter-only mode for selected methods */
-    char jitMethodBuf[sizeof("-Xjitmethod:") + PROPERTY_VALUE_MAX];
     property_get("dalvik.vm.jit.method", propBuf, "");
     if (strlen(propBuf) > 0) {
         strcpy(jitMethodBuf, "-Xjitmethod:");
@@ -742,14 +762,26 @@
         mOptions.add(opt);
     }
 
+    // libart tolerates libdvm flags, but not vice versa, so only pass some options if libart.
+    property_get("persist.sys.dalvik.vm.lib.1", dalvikVmLibBuf, "libdvm.so");
+    bool libart = (strncmp(dalvikVmLibBuf, "libart", 6) == 0);
+
+    if (libart) {
+        // Extra options for DexClassLoader.
+        property_get("dalvik.vm.dex2oat-flags", dex2oatFlagsBuf, "");
+        parseExtraOpts(dex2oatFlagsBuf, "-Xcompiler-option");
+
+        // Extra options for boot.art/boot.oat image generation.
+        property_get("dalvik.vm.image-dex2oat-flags", dex2oatImageFlagsBuf, "");
+        parseExtraOpts(dex2oatImageFlagsBuf, "-Ximage-compiler-option");
+    }
+
     /* extra options; parse this late so it overrides others */
     property_get("dalvik.vm.extra-opts", extraOptsBuf, "");
-    parseExtraOpts(extraOptsBuf);
+    parseExtraOpts(extraOptsBuf, NULL);
 
     /* Set the properties for locale */
     {
-        char langOption[sizeof("-Duser.language=") + 3];
-        char regionOption[sizeof("-Duser.region=") + 3];
         strcpy(langOption, "-Duser.language=");
         strcpy(regionOption, "-Duser.region=");
         readLocale(langOption, regionOption);
@@ -761,11 +793,35 @@
     }
 
     /*
-     * We don't have /tmp on the device, but we often have an SD card.  Apps
-     * shouldn't use this, but some test suites might want to exercise it.
+     * Set profiler options
      */
-    opt.optionString = "-Djava.io.tmpdir=/sdcard";
-    mOptions.add(opt);
+    if (libart) {
+      // Number of seconds during profile runs.
+      strcpy(profile_period, "-Xprofile-period:");
+      property_get("dalvik.vm.profile.period_secs", profile_period+17, "10");
+      opt.optionString = profile_period;
+      mOptions.add(opt);
+
+      // Length of each profile run (seconds).
+      strcpy(profile_duration, "-Xprofile-duration:");
+      property_get("dalvik.vm.profile.duration_secs", profile_duration+19, "30");
+      opt.optionString = profile_duration;
+      mOptions.add(opt);
+
+
+      // Polling interval during profile run (microseconds).
+      strcpy(profile_interval, "-Xprofile-interval:");
+      property_get("dalvik.vm.profile.interval_us", profile_interval+19, "10000");
+      opt.optionString = profile_interval;
+      mOptions.add(opt);
+
+      // Coefficient for period backoff.  The the period is multiplied
+      // by this value after each profile run.
+      strcpy(profile_backoff, "-Xprofile-backoff:");
+      property_get("dalvik.vm.profile.backoff_coeff", profile_backoff+18, "2.0");
+      opt.optionString = profile_backoff;
+      mOptions.add(opt);
+    }
 
     initArgs.version = JNI_VERSION_1_4;
     initArgs.options = mOptions.editArray();
@@ -1100,7 +1156,6 @@
 }
 
 static const RegJNIRec gRegJNI[] = {
-    REG_JNI(register_android_debug_JNITest),
     REG_JNI(register_com_android_internal_os_RuntimeInit),
     REG_JNI(register_android_os_SystemClock),
     REG_JNI(register_android_util_EventLog),
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 56d903c..13c1fc8 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -106,17 +106,19 @@
     chunk->paddingRight = int(chunk->paddingRight * scale + 0.5f);
     chunk->paddingBottom = int(chunk->paddingBottom * scale + 0.5f);
 
+    int32_t* xDivs = chunk->getXDivs();
     for (int i = 0; i < chunk->numXDivs; i++) {
-        chunk->xDivs[i] = int(chunk->xDivs[i] * scale + 0.5f);
-        if (i > 0 && chunk->xDivs[i] == chunk->xDivs[i - 1]) {
-            chunk->xDivs[i]++;
+        xDivs[i] = int32_t(xDivs[i] * scale + 0.5f);
+        if (i > 0 && xDivs[i] == xDivs[i - 1]) {
+            xDivs[i]++;
         }
     }
 
+    int32_t* yDivs = chunk->getXDivs();
     for (int i = 0; i < chunk->numYDivs; i++) {
-        chunk->yDivs[i] = int(chunk->yDivs[i] * scale + 0.5f);
-        if (i > 0 && chunk->yDivs[i] == chunk->yDivs[i - 1]) {
-            chunk->yDivs[i]++;
+        yDivs[i] = int32_t(yDivs[i] * scale + 0.5f);
+        if (i > 0 && yDivs[i] == yDivs[i - 1]) {
+            yDivs[i]++;
         }
     }
 }
@@ -365,7 +367,7 @@
             return nullObjectReturn("primitive array == null");
         }
 
-        peeker.fPatch->serialize(array);
+        memcpy(array, peeker.fPatch, peeker.fPatchSize);
         env->ReleasePrimitiveArrayCritical(ninePatchChunk, array, 0);
     }
 
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 89490bc..11089da 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -321,9 +321,10 @@
     }
 
     static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle,
-                             SkPath* path, jint op) {
+                             jlong pathHandle, jint op) {
         SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
-        bool result = canvas->clipPath(*path, static_cast<SkRegion::Op>(op));
+        bool result = canvas->clipPath(*reinterpret_cast<SkPath*>(pathHandle),
+                                       static_cast<SkRegion::Op>(op));
         return result ? JNI_TRUE : JNI_FALSE;
     }
 
@@ -336,9 +337,9 @@
     }
 
     static void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle,
-                              SkDrawFilter* filter) {
+                              jlong filterHandle) {
         SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
-        canvas->setDrawFilter(filter);
+        canvas->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
     }
 
     static jboolean quickReject__RectF(JNIEnv* env, jobject, jlong canvasHandle,
@@ -350,9 +351,9 @@
     }
 
     static jboolean quickReject__Path(JNIEnv* env, jobject, jlong canvasHandle,
-                                       SkPath* path) {
+                                       jlong pathHandle) {
         SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
-        bool result = canvas->quickReject(*path);
+        bool result = canvas->quickReject(*reinterpret_cast<SkPath*>(pathHandle));
         return result ? JNI_TRUE : JNI_FALSE;
     }
 
diff --git a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
index da8f083..2cb1015 100644
--- a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
+++ b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
@@ -63,9 +63,14 @@
         size_t bytesRead = 0;
         // read the bytes
         do {
-            size_t requested = size;
-            if (requested > fCapacity)
+            jint requested = 0;
+            if (size > static_cast<size_t>(fCapacity)) {
                 requested = fCapacity;
+            } else {
+                // This is safe because requested is clamped to (jint)
+                // fCapacity.
+                requested = static_cast<jint>(size);
+            }
 
             jint n = env->CallIntMethod(fJavaInputStream,
                                         gInputStream_readMethodID, fJavaByteArray, 0, requested);
@@ -120,7 +125,7 @@
     JNIEnv*     fEnv;
     jobject     fJavaInputStream;   // the caller owns this object
     jbyteArray  fJavaByteArray;     // the caller owns this object
-    size_t      fCapacity;
+    jint        fCapacity;
     size_t      fBytesRead;
     bool        fIsAtEnd;
 };
@@ -174,14 +179,18 @@
         fCapacity = env->GetArrayLength(storage);
     }
 
-	virtual bool write(const void* buffer, size_t size) {
+    virtual bool write(const void* buffer, size_t size) {
         JNIEnv* env = fEnv;
         jbyteArray storage = fJavaByteArray;
 
         while (size > 0) {
-            size_t requested = size;
-            if (requested > fCapacity) {
+            jint requested = 0;
+            if (size > static_cast<size_t>(fCapacity)) {
                 requested = fCapacity;
+            } else {
+                // This is safe because requested is clamped to (jint)
+                // fCapacity.
+                requested = static_cast<jint>(size);
             }
 
             env->SetByteArrayRegion(storage, 0, requested,
@@ -216,7 +225,7 @@
     JNIEnv*     fEnv;
     jobject     fJavaOutputStream;  // the caller owns this object
     jbyteArray  fJavaByteArray;     // the caller owns this object
-    size_t      fCapacity;
+    jint        fCapacity;
 };
 
 SkWStream* CreateJavaOutputStreamAdaptor(JNIEnv* env, jobject stream,
diff --git a/core/jni/android/graphics/NinePatchImpl.cpp b/core/jni/android/graphics/NinePatchImpl.cpp
index 01e7e3e..86ff13c 100644
--- a/core/jni/android/graphics/NinePatchImpl.cpp
+++ b/core/jni/android/graphics/NinePatchImpl.cpp
@@ -115,13 +115,15 @@
         defaultPaint.setDither(true);
         paint = &defaultPaint;
     }
-    
+   
+    const int32_t* xDivs = chunk.getXDivs();
+    const int32_t* yDivs = chunk.getYDivs();
     // if our SkCanvas were back by GL we should enable this and draw this as
     // a mesh, which will be faster in most cases.
     if (false) {
         SkNinePatch::DrawMesh(canvas, bounds, bitmap,
-                              chunk.xDivs, chunk.numXDivs,
-                              chunk.yDivs, chunk.numYDivs,
+                              xDivs, chunk.numXDivs,
+                              yDivs, chunk.numYDivs,
                               paint);
         return;
     }
@@ -145,8 +147,8 @@
     if (gTrace) {
         ALOGV("======== ninepatch bounds [%g %g]\n", SkScalarToFloat(bounds.width()), SkScalarToFloat(bounds.height()));
         ALOGV("======== ninepatch paint bm [%d,%d]\n", bitmap.width(), bitmap.height());
-        ALOGV("======== ninepatch xDivs [%d,%d]\n", chunk.xDivs[0], chunk.xDivs[1]);
-        ALOGV("======== ninepatch yDivs [%d,%d]\n", chunk.yDivs[0], chunk.yDivs[1]);
+        ALOGV("======== ninepatch xDivs [%d,%d]\n", xDivs[0], xDivs[1]);
+        ALOGV("======== ninepatch yDivs [%d,%d]\n", yDivs[0], yDivs[1]);
     }
 #endif
 
@@ -171,8 +173,8 @@
     SkRect      dst;
     SkIRect     src;
 
-    const int32_t x0 = chunk.xDivs[0];
-    const int32_t y0 = chunk.yDivs[0];
+    const int32_t x0 = xDivs[0];
+    const int32_t y0 = yDivs[0];
     const SkColor initColor = ((SkPaint*)paint)->getColor();
     const uint8_t numXDivs = chunk.numXDivs;
     const uint8_t numYDivs = chunk.numYDivs;
@@ -191,12 +193,12 @@
 
     int numStretchyXPixelsRemaining = 0;
     for (i = 0; i < numXDivs; i += 2) {
-        numStretchyXPixelsRemaining += chunk.xDivs[i + 1] - chunk.xDivs[i];
+        numStretchyXPixelsRemaining += xDivs[i + 1] - xDivs[i];
     }
     int numFixedXPixelsRemaining = bitmapWidth - numStretchyXPixelsRemaining;
     int numStretchyYPixelsRemaining = 0;
     for (i = 0; i < numYDivs; i += 2) {
-        numStretchyYPixelsRemaining += chunk.yDivs[i + 1] - chunk.yDivs[i];
+        numStretchyYPixelsRemaining += yDivs[i + 1] - yDivs[i];
     }
     int numFixedYPixelsRemaining = bitmapHeight - numStretchyYPixelsRemaining;
 
@@ -235,7 +237,7 @@
             src.fBottom = bitmapHeight;
             dst.fBottom = bounds.fBottom;
         } else {
-            src.fBottom = chunk.yDivs[j];
+            src.fBottom = yDivs[j];
             const int srcYSize = src.fBottom - src.fTop;
             if (yIsStretchable) {
                 dst.fBottom = dst.fTop + calculateStretch(bounds.fBottom, dst.fTop,
@@ -252,15 +254,16 @@
         xIsStretchable = initialXIsStretchable;
         // The initial xDiv and whether the first column is considered
         // stretchable or not depends on whether xDiv[0] was zero or not.
+        const uint32_t* colors = chunk.getColors();
         for (i = xIsStretchable ? 1 : 0;
               i <= numXDivs && src.fLeft < bitmapWidth;
               i++, xIsStretchable = !xIsStretchable) {
-            color = chunk.colors[colorIndex++];
+            color = colors[colorIndex++];
             if (i == numXDivs) {
                 src.fRight = bitmapWidth;
                 dst.fRight = bounds.fRight;
             } else {
-                src.fRight = chunk.xDivs[i];
+                src.fRight = xDivs[i];
                 if (dstRightsHaveBeenCached) {
                     dst.fRight = dstRights[i];
                 } else {
diff --git a/core/jni/android/graphics/NinePatchPeeker.cpp b/core/jni/android/graphics/NinePatchPeeker.cpp
index df996af..51392ab 100644
--- a/core/jni/android/graphics/NinePatchPeeker.cpp
+++ b/core/jni/android/graphics/NinePatchPeeker.cpp
@@ -28,11 +28,11 @@
         // You have to copy the data because it is owned by the png reader
         Res_png_9patch* patchNew = (Res_png_9patch*) malloc(patchSize);
         memcpy(patchNew, patch, patchSize);
-        // this relies on deserialization being done in place
         Res_png_9patch::deserialize(patchNew);
         patchNew->fileToDevice();
         free(fPatch);
         fPatch = patchNew;
+        fPatchSize = patchSize;
         //printf("9patch: (%d,%d)-(%d,%d)\n",
         //       fPatch.sizeLeft, fPatch.sizeTop,
         //       fPatch.sizeRight, fPatch.sizeBottom);
diff --git a/core/jni/android/graphics/NinePatchPeeker.h b/core/jni/android/graphics/NinePatchPeeker.h
index 10d268a..2043862 100644
--- a/core/jni/android/graphics/NinePatchPeeker.h
+++ b/core/jni/android/graphics/NinePatchPeeker.h
@@ -29,6 +29,7 @@
         // the host lives longer than we do, so a raw ptr is safe
         fHost = host;
         fPatch = NULL;
+        fPatchSize = 0;
         fLayoutBounds = NULL;
     }
 
@@ -38,6 +39,7 @@
     }
 
     Res_png_9patch*  fPatch;
+    size_t fPatchSize;
     int    *fLayoutBounds;
 
     virtual bool peek(const char tag[], const void* data, size_t length);
diff --git a/core/jni/android_debug_JNITest.cpp b/core/jni/android_debug_JNITest.cpp
deleted file mode 100644
index 9147284..0000000
--- a/core/jni/android_debug_JNITest.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/* //device/libs/android_runtime/android_debug_JNITest.cpp
-**
-** Copyright 2006, 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.
-*/
-
-#define LOG_TAG "DebugJNI"
-
-#include "jni.h"
-#include "nativehelper/JNIHelp.h"
-#include "utils/Log.h"
-#include "utils/misc.h"
-//#include "android_runtime/AndroidRuntime.h"
-
-namespace android {
-
-/*
- * Implements:
- *  native int part1(int intArg, double doubleArg, String stringArg,
- *      int[] arrayArg)
- */
-static jint android_debug_JNITest_part1(JNIEnv* env, jobject object,
-    jint intArg, jdouble doubleArg, jstring stringArg, jobjectArray arrayArg)
-{
-    jclass clazz;
-    jmethodID part2id;
-    jsize arrayLen;
-    jint arrayVal;
-    int result = -2;
-
-    ALOGI("JNI test: in part1, intArg=%d, doubleArg=%.3f\n", intArg, doubleArg);
-
-    /* find "int part2(double doubleArg, int fromArray, String stringArg)" */
-    clazz = env->GetObjectClass(object);
-    part2id = env->GetMethodID(clazz,
-                "part2", "(DILjava/lang/String;)I");
-    if (part2id == NULL) {
-        ALOGE("JNI test: unable to find part2\n");
-        return -1;
-    }
-
-    /* get the length of the array */
-    arrayLen = env->GetArrayLength(arrayArg);
-    ALOGI("  array size is %d\n", arrayLen);
-
-    /*
-     * Get the last element in the array.
-     * Use the Get<type>ArrayElements functions instead if you need access
-     * to multiple elements.
-     */
-    arrayVal = (int) env->GetObjectArrayElement(arrayArg, arrayLen-1);
-    ALOGI("  array val is %d\n", arrayVal);
-
-    /* call this->part2 */
-    result = env->CallIntMethod(object, part2id,
-        doubleArg, arrayVal, stringArg);
-
-    return result;
-}
-
-/*
- * Implements:
- *  private static native int part3(String stringArg);
- */
-static jint android_debug_JNITest_part3(JNIEnv* env, jclass clazz,
-    jstring stringArg)
-{
-    const char* utfChars;
-    jboolean isCopy;
-
-    ALOGI("JNI test: in part3\n");
-
-    utfChars = env->GetStringUTFChars(stringArg, &isCopy);
-
-    ALOGI("  String is '%s', isCopy=%d\n", (const char*) utfChars, isCopy);
-
-    env->ReleaseStringUTFChars(stringArg, utfChars);
-
-    return 2000;
-}
-
-/*
- * JNI registration.
- */
-static JNINativeMethod gMethods[] = {
-    /* name, signature, funcPtr */
-    { "part1",      "(IDLjava/lang/String;[I)I",
-            (void*) android_debug_JNITest_part1 },
-    { "part3",      "(Ljava/lang/String;)I",
-            (void*) android_debug_JNITest_part3 },
-};
-int register_android_debug_JNITest(JNIEnv* env)
-{
-    return jniRegisterNativeMethods(env, "android/debug/JNITest",
-        gMethods, NELEM(gMethods));
-}
-
-#if 0
-/* trampoline into C++ */
-extern "C"
-int register_android_debug_JNITest_C(JNIEnv* env)
-{
-    return android::register_android_debug_JNITest(env);
-}
-#endif
-
-}; // namespace android
-
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index b22668b..ab70f25 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -18,6 +18,7 @@
 
 #define LOG_TAG "AudioRecord-JNI"
 
+#include <inttypes.h>
 #include <jni.h>
 #include <JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
@@ -316,7 +317,7 @@
     if (lpRecorder == NULL) {
         return;
     }
-    ALOGV("About to delete lpRecorder: %x\n", (int)lpRecorder.get());
+    ALOGV("About to delete lpRecorder: %" PRIxPTR "\n", lpRecorder.get());
     lpRecorder->stop();
 
     audiorecord_callback_cookie *lpCookie = (audiorecord_callback_cookie *)env->GetLongField(
@@ -329,7 +330,7 @@
     // delete the callback information
     if (lpCookie) {
         Mutex::Autolock l(sLock);
-        ALOGV("deleting lpCookie: %x\n", (int)lpCookie);
+        ALOGV("deleting lpCookie: %" PRIxPTR "\n", lpCookie);
         while (lpCookie->busy) {
             if (lpCookie->cond.waitRelative(sLock,
                                             milliseconds(CALLBACK_COND_WAIT_TIMEOUT_MS)) !=
diff --git a/core/jni/android_opengl_EGL14.cpp b/core/jni/android_opengl_EGL14.cpp
index 5b0a4b2..19e4d99 100644
--- a/core/jni/android_opengl_EGL14.cpp
+++ b/core/jni/android_opengl_EGL14.cpp
@@ -69,22 +69,22 @@
     jclass eglconfigClassLocal = _env->FindClass("android/opengl/EGLConfig");
     eglconfigClass = (jclass) _env->NewGlobalRef(eglconfigClassLocal);
 
-    egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getHandle", "()I");
-    eglcontextGetHandleID = _env->GetMethodID(eglcontextClass, "getHandle", "()I");
-    eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getHandle", "()I");
-    eglconfigGetHandleID = _env->GetMethodID(eglconfigClass, "getHandle", "()I");
+    egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getNativeHandle", "()J");
+    eglcontextGetHandleID = _env->GetMethodID(eglcontextClass, "getNativeHandle", "()J");
+    eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getNativeHandle", "()J");
+    eglconfigGetHandleID = _env->GetMethodID(eglconfigClass, "getNativeHandle", "()J");
 
 
-    egldisplayConstructor = _env->GetMethodID(egldisplayClass, "<init>", "(I)V");
-    eglcontextConstructor = _env->GetMethodID(eglcontextClass, "<init>", "(I)V");
-    eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(I)V");
-    eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(I)V");
+    egldisplayConstructor = _env->GetMethodID(egldisplayClass, "<init>", "(J)V");
+    eglcontextConstructor = _env->GetMethodID(eglcontextClass, "<init>", "(J)V");
+    eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(J)V");
+    eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(J)V");
 
-    jobject localeglNoContextObject = _env->NewObject(eglcontextClass, eglcontextConstructor, (jint)EGL_NO_CONTEXT);
+    jobject localeglNoContextObject = _env->NewObject(eglcontextClass, eglcontextConstructor, reinterpret_cast<jlong>(EGL_NO_CONTEXT));
     eglNoContextObject = _env->NewGlobalRef(localeglNoContextObject);
-    jobject localeglNoDisplayObject = _env->NewObject(egldisplayClass, egldisplayConstructor, (jint)EGL_NO_DISPLAY);
+    jobject localeglNoDisplayObject = _env->NewObject(egldisplayClass, egldisplayConstructor, reinterpret_cast<jlong>(EGL_NO_DISPLAY));
     eglNoDisplayObject = _env->NewGlobalRef(localeglNoDisplayObject);
-    jobject localeglNoSurfaceObject = _env->NewObject(eglsurfaceClass, eglsurfaceConstructor, (jint)EGL_NO_SURFACE);
+    jobject localeglNoSurfaceObject = _env->NewObject(eglsurfaceClass, eglsurfaceConstructor, reinterpret_cast<jlong>(EGL_NO_SURFACE));
     eglNoSurfaceObject = _env->NewGlobalRef(localeglNoSurfaceObject);
 
 
@@ -106,7 +106,8 @@
                           "Object is set to null.");
     }
 
-    return (void*) (_env->CallIntMethod(obj, mid));
+    jlong handle = _env->CallLongMethod(obj, mid);
+    return reinterpret_cast<void*>(handle);
 }
 
 static jobject
@@ -126,7 +127,7 @@
            return eglNoSurfaceObject;
     }
 
-    return _env->NewObject(cls, con, (jint)handle);
+    return _env->NewObject(cls, con, reinterpret_cast<jlong>(handle));
 }
 
 // --------------------------------------------------------------------------
@@ -142,14 +143,26 @@
 /* EGLDisplay eglGetDisplay ( EGLNativeDisplayType display_id ) */
 static jobject
 android_eglGetDisplay
-  (JNIEnv *_env, jobject _this, jint display_id) {
+  (JNIEnv *_env, jobject _this, jlong display_id) {
     EGLDisplay _returnValue = (EGLDisplay) 0;
     _returnValue = eglGetDisplay(
-        (EGLNativeDisplayType)display_id
+        reinterpret_cast<EGLNativeDisplayType>(display_id)
     );
     return toEGLHandle(_env, egldisplayClass, egldisplayConstructor, _returnValue);
 }
 
+/* EGLDisplay eglGetDisplay ( EGLNativeDisplayType display_id ) */
+static jobject
+android_eglGetDisplayInt
+  (JNIEnv *_env, jobject _this, jint display_id) {
+
+    if ((EGLNativeDisplayType)display_id != EGL_DEFAULT_DISPLAY) {
+        jniThrowException(_env, "java/lang/UnsupportedOperationException", "eglGetDisplay");
+        return 0;
+    }
+    return android_eglGetDisplay(_env, _this, display_id);
+}
+
 /* EGLBoolean eglInitialize ( EGLDisplay dpy, EGLint *major, EGLint *minor ) */
 static jboolean
 android_eglInitialize
@@ -852,7 +865,7 @@
 /* EGLSurface eglCreatePbufferFromClientBuffer ( EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list ) */
 static jobject
 android_eglCreatePbufferFromClientBuffer
-  (JNIEnv *_env, jobject _this, jobject dpy, jint buftype, jint buffer, jobject config, jintArray attrib_list_ref, jint offset) {
+  (JNIEnv *_env, jobject _this, jobject dpy, jint buftype, jlong buffer, jobject config, jintArray attrib_list_ref, jint offset) {
     jint _exception = 0;
     const char * _exceptionType = NULL;
     const char * _exceptionMessage = NULL;
@@ -897,7 +910,7 @@
     _returnValue = eglCreatePbufferFromClientBuffer(
         (EGLDisplay)dpy_native,
         (EGLenum)buftype,
-        (EGLClientBuffer)buffer,
+        reinterpret_cast<EGLClientBuffer>(buffer),
         (EGLConfig)config_native,
         (EGLint *)attrib_list
     );
@@ -913,6 +926,16 @@
     return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
 }
 
+static jobject
+android_eglCreatePbufferFromClientBufferInt
+  (JNIEnv *_env, jobject _this, jobject dpy, jint buftype, jint buffer, jobject config, jintArray attrib_list_ref, jint offset) {
+    if(sizeof(void*) != sizeof(uint32_t)) {
+        jniThrowException(_env, "java/lang/UnsupportedOperationException", "eglCreatePbufferFromClientBuffer");
+        return 0;
+    }
+    return android_eglCreatePbufferFromClientBuffer(_env, _this, dpy, buftype, buffer, config, attrib_list_ref, offset);
+}
+
 /* EGLBoolean eglSurfaceAttrib ( EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value ) */
 static jboolean
 android_eglSurfaceAttrib
@@ -1207,7 +1230,8 @@
 static JNINativeMethod methods[] = {
 {"_nativeClassInit", "()V", (void*)nativeClassInit },
 {"eglGetError", "()I", (void *) android_eglGetError },
-{"eglGetDisplay", "(I)Landroid/opengl/EGLDisplay;", (void *) android_eglGetDisplay },
+{"eglGetDisplay", "(I)Landroid/opengl/EGLDisplay;", (void *) android_eglGetDisplayInt },
+{"eglGetDisplay", "(J)Landroid/opengl/EGLDisplay;", (void *) android_eglGetDisplay },
 {"eglInitialize", "(Landroid/opengl/EGLDisplay;[II[II)Z", (void *) android_eglInitialize },
 {"eglTerminate", "(Landroid/opengl/EGLDisplay;)Z", (void *) android_eglTerminate },
 {"eglQueryString", "(Landroid/opengl/EGLDisplay;I)Ljava/lang/String;", (void *) android_eglQueryString__Landroind_opengl_EGLDisplay_2I },
@@ -1224,7 +1248,8 @@
 {"eglQueryAPI", "()I", (void *) android_eglQueryAPI },
 {"eglWaitClient", "()Z", (void *) android_eglWaitClient },
 {"eglReleaseThread", "()Z", (void *) android_eglReleaseThread },
-{"eglCreatePbufferFromClientBuffer", "(Landroid/opengl/EGLDisplay;IILandroid/opengl/EGLConfig;[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePbufferFromClientBuffer },
+{"eglCreatePbufferFromClientBuffer", "(Landroid/opengl/EGLDisplay;IILandroid/opengl/EGLConfig;[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePbufferFromClientBufferInt },
+{"eglCreatePbufferFromClientBuffer", "(Landroid/opengl/EGLDisplay;IJLandroid/opengl/EGLConfig;[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePbufferFromClientBuffer },
 {"eglSurfaceAttrib", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;II)Z", (void *) android_eglSurfaceAttrib },
 {"eglBindTexImage", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;I)Z", (void *) android_eglBindTexImage },
 {"eglReleaseTexImage", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;I)Z", (void *) android_eglReleaseTexImage },
diff --git a/core/jni/android_opengl_EGLExt.cpp b/core/jni/android_opengl_EGLExt.cpp
index 5179ddc..15899f5 100644
--- a/core/jni/android_opengl_EGLExt.cpp
+++ b/core/jni/android_opengl_EGLExt.cpp
@@ -70,22 +70,22 @@
     jclass eglconfigClassLocal = _env->FindClass("android/opengl/EGLConfig");
     eglconfigClass = (jclass) _env->NewGlobalRef(eglconfigClassLocal);
 
-    egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getHandle", "()I");
-    eglcontextGetHandleID = _env->GetMethodID(eglcontextClass, "getHandle", "()I");
-    eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getHandle", "()I");
-    eglconfigGetHandleID = _env->GetMethodID(eglconfigClass, "getHandle", "()I");
+    egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getNativeHandle", "()J");
+    eglcontextGetHandleID = _env->GetMethodID(eglcontextClass, "getNativeHandle", "()J");
+    eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getNativeHandle", "()J");
+    eglconfigGetHandleID = _env->GetMethodID(eglconfigClass, "getNativeHandle", "()J");
 
 
-    egldisplayConstructor = _env->GetMethodID(egldisplayClass, "<init>", "(I)V");
-    eglcontextConstructor = _env->GetMethodID(eglcontextClass, "<init>", "(I)V");
-    eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(I)V");
-    eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(I)V");
+    egldisplayConstructor = _env->GetMethodID(egldisplayClass, "<init>", "(J)V");
+    eglcontextConstructor = _env->GetMethodID(eglcontextClass, "<init>", "(J)V");
+    eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(J)V");
+    eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(J)V");
 
-    jobject localeglNoContextObject = _env->NewObject(eglcontextClass, eglcontextConstructor, (jint)EGL_NO_CONTEXT);
+    jobject localeglNoContextObject = _env->NewObject(eglcontextClass, eglcontextConstructor, reinterpret_cast<jlong>(EGL_NO_CONTEXT));
     eglNoContextObject = _env->NewGlobalRef(localeglNoContextObject);
-    jobject localeglNoDisplayObject = _env->NewObject(egldisplayClass, egldisplayConstructor, (jint)EGL_NO_DISPLAY);
+    jobject localeglNoDisplayObject = _env->NewObject(egldisplayClass, egldisplayConstructor, reinterpret_cast<jlong>(EGL_NO_DISPLAY));
     eglNoDisplayObject = _env->NewGlobalRef(localeglNoDisplayObject);
-    jobject localeglNoSurfaceObject = _env->NewObject(eglsurfaceClass, eglsurfaceConstructor, (jint)EGL_NO_SURFACE);
+    jobject localeglNoSurfaceObject = _env->NewObject(eglsurfaceClass, eglsurfaceConstructor, reinterpret_cast<jlong>(EGL_NO_SURFACE));
     eglNoSurfaceObject = _env->NewGlobalRef(localeglNoSurfaceObject);
 
 
@@ -107,7 +107,7 @@
                           "Object is set to null.");
     }
 
-    return (void*) (_env->CallIntMethod(obj, mid));
+    return reinterpret_cast<void*>(_env->CallLongMethod(obj, mid));
 }
 
 static jobject
@@ -127,7 +127,7 @@
            return eglNoSurfaceObject;
     }
 
-    return _env->NewObject(cls, con, (jint)handle);
+    return _env->NewObject(cls, con, reinterpret_cast<jlong>(handle));
 }
 
 // --------------------------------------------------------------------------
diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp
index cc34e99..21e19e1 100644
--- a/core/jni/android_opengl_GLES10.cpp
+++ b/core/jni/android_opengl_GLES10.cpp
@@ -111,7 +111,7 @@
             getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void*>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
diff --git a/core/jni/android_opengl_GLES10Ext.cpp b/core/jni/android_opengl_GLES10Ext.cpp
index 9284384..bc83234 100644
--- a/core/jni/android_opengl_GLES10Ext.cpp
+++ b/core/jni/android_opengl_GLES10Ext.cpp
@@ -111,7 +111,7 @@
             getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void*>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
diff --git a/core/jni/android_opengl_GLES11.cpp b/core/jni/android_opengl_GLES11.cpp
index 871e84d..a45f269 100644
--- a/core/jni/android_opengl_GLES11.cpp
+++ b/core/jni/android_opengl_GLES11.cpp
@@ -111,7 +111,7 @@
             getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void*>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
@@ -578,7 +578,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -679,7 +679,7 @@
         (GLenum)mode,
         (GLsizei)count,
         (GLenum)type,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
     if (_exception) {
         jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -2302,7 +2302,7 @@
     glNormalPointer(
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -2529,7 +2529,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -2937,7 +2937,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
diff --git a/core/jni/android_opengl_GLES11Ext.cpp b/core/jni/android_opengl_GLES11Ext.cpp
index 3e038ad..05728ef 100644
--- a/core/jni/android_opengl_GLES11Ext.cpp
+++ b/core/jni/android_opengl_GLES11Ext.cpp
@@ -111,7 +111,7 @@
             getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void*>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
diff --git a/core/jni/android_opengl_GLES20.cpp b/core/jni/android_opengl_GLES20.cpp
index db03b70..d3e5014 100644
--- a/core/jni/android_opengl_GLES20.cpp
+++ b/core/jni/android_opengl_GLES20.cpp
@@ -111,7 +111,7 @@
             getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void*>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
@@ -1180,7 +1180,7 @@
         (GLenum)mode,
         (GLsizei)count,
         (GLenum)type,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
     if (_exception) {
         jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -1804,7 +1804,7 @@
         (GLsizei *)length,
         (GLint *)size,
         (GLenum *)type,
-        (char *)name
+        reinterpret_cast<char *>(name)
     );
     if (_typeArray) {
         releasePointer(_env, _typeArray, type, JNI_TRUE);
@@ -2132,7 +2132,7 @@
         (GLsizei *)length,
         (GLint *)size,
         (GLenum *)type,
-        (char *)name
+        reinterpret_cast<char *>(name)
     );
     if (_typeArray) {
         releasePointer(_env, _typeArray, type, JNI_TRUE);
@@ -3212,7 +3212,7 @@
         (GLuint)shader,
         (GLsizei)bufsize,
         (GLsizei *)length,
-        (char *)source
+        reinterpret_cast<char *>(source)
     );
     if (_array) {
         releasePointer(_env, _array, length, JNI_TRUE);
@@ -5985,7 +5985,7 @@
         (GLenum)type,
         (GLboolean)normalized,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
diff --git a/core/jni/android_opengl_GLES30.cpp b/core/jni/android_opengl_GLES30.cpp
index 4c62a75..8821352 100644
--- a/core/jni/android_opengl_GLES30.cpp
+++ b/core/jni/android_opengl_GLES30.cpp
@@ -111,7 +111,7 @@
             getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void*>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
@@ -370,7 +370,7 @@
         (GLuint)end,
         (GLsizei)count,
         (GLenum)type,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -419,7 +419,7 @@
         (GLint)border,
         (GLenum)format,
         (GLenum)type,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -470,7 +470,7 @@
         (GLsizei)depth,
         (GLenum)format,
         (GLenum)type,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -534,7 +534,7 @@
         (GLsizei)depth,
         (GLint)border,
         (GLsizei)imageSize,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -585,7 +585,7 @@
         (GLsizei)depth,
         (GLenum)format,
         (GLsizei)imageSize,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -2134,7 +2134,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
diff --git a/core/jni/android_os_SystemClock.cpp b/core/jni/android_os_SystemClock.cpp
index 5f4d570..6247844 100644
--- a/core/jni/android_os_SystemClock.cpp
+++ b/core/jni/android_os_SystemClock.cpp
@@ -19,13 +19,6 @@
  * System clock functions.
  */
 
-#ifdef HAVE_ANDROID_OS
-#include <linux/ioctl.h>
-#include <linux/rtc.h>
-#include <utils/Atomic.h>
-#include <linux/android_alarm.h>
-#endif
-
 #include <sys/time.h>
 #include <limits.h>
 #include <fcntl.h>
@@ -43,109 +36,6 @@
 
 namespace android {
 
-static int setCurrentTimeMillisAlarmDriver(struct timeval *tv)
-{
-    struct timespec ts;
-    int fd;
-    int res;
-
-    fd = open("/dev/alarm", O_RDWR);
-    if(fd < 0) {
-        ALOGV("Unable to open alarm driver: %s\n", strerror(errno));
-        return -1;
-    }
-    ts.tv_sec = tv->tv_sec;
-    ts.tv_nsec = tv->tv_usec * 1000;
-    res = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts);
-    if (res < 0)
-        ALOGV("ANDROID_ALARM_SET_RTC ioctl failed: %s\n", strerror(errno));
-    close(fd);
-    return res;
-}
-
-static int setCurrentTimeMillisRtc(struct timeval *tv)
-{
-    struct rtc_time rtc;
-    struct tm tm, *gmtime_res;
-    int fd;
-    int res;
-
-    fd = open("/dev/rtc0", O_RDWR);
-    if (fd < 0) {
-        ALOGV("Unable to open RTC driver: %s\n", strerror(errno));
-        return -1;
-    }
-
-    res = settimeofday(tv, NULL);
-    if (res < 0) {
-        ALOGV("settimeofday() failed: %s\n", strerror(errno));
-        goto done;
-    }
-
-    gmtime_res = gmtime_r(&tv->tv_sec, &tm);
-    if (!gmtime_res) {
-        ALOGV("gmtime_r() failed: %s\n", strerror(errno));
-        res = -1;
-        goto done;
-    }
-
-    memset(&rtc, 0, sizeof(rtc));
-    rtc.tm_sec = tm.tm_sec;
-    rtc.tm_min = tm.tm_min;
-    rtc.tm_hour = tm.tm_hour;
-    rtc.tm_mday = tm.tm_mday;
-    rtc.tm_mon = tm.tm_mon;
-    rtc.tm_year = tm.tm_year;
-    rtc.tm_wday = tm.tm_wday;
-    rtc.tm_yday = tm.tm_yday;
-    rtc.tm_isdst = tm.tm_isdst;
-    res = ioctl(fd, RTC_SET_TIME, &rtc);
-    if (res < 0)
-        ALOGV("RTC_SET_TIME ioctl failed: %s\n", strerror(errno));
-done:
-    close(fd);
-    return res;
-}
-
-/*
- * Set the current time.  This only works when running as root.
- */
-static int setCurrentTimeMillis(int64_t millis)
-{
-    struct timeval tv;
-    int ret;
-
-    if (millis <= 0 || millis / 1000LL >= INT_MAX) {
-        return -1;
-    }
-
-    tv.tv_sec = (time_t) (millis / 1000LL);
-    tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL);
-
-    ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec);
-
-    ret = setCurrentTimeMillisAlarmDriver(&tv);
-    if (ret < 0)
-        ret = setCurrentTimeMillisRtc(&tv);
-
-    if(ret < 0) {
-        ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno));
-        ret = -1;
-    }
-    return ret;
-}
-
-/*
- * native public static void setCurrentTimeMillis(long millis)
- *
- * Set the current time.  This only works when running as root.
- */
-static jboolean android_os_SystemClock_setCurrentTimeMillis(JNIEnv* env,
-    jobject clazz, jlong millis)
-{
-    return (setCurrentTimeMillis(millis) == 0);
-}
-
 /*
  * native public static long uptimeMillis();
  */
@@ -230,8 +120,6 @@
  */
 static JNINativeMethod gMethods[] = {
     /* name, signature, funcPtr */
-    { "setCurrentTimeMillis",      "(J)Z",
-            (void*) android_os_SystemClock_setCurrentTimeMillis },
     { "uptimeMillis",      "()J",
             (void*) android_os_SystemClock_uptimeMillis },
     { "elapsedRealtime",      "()J",
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 118af1b..591ff77 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -118,14 +118,12 @@
 // ----------------------------------------------------------------------------
 
 static void android_view_GLES20Canvas_initAtlas(JNIEnv* env, jobject clazz,
-        jobject graphicBuffer, jintArray atlasMapArray, jint count) {
+        jobject graphicBuffer, jlongArray atlasMapArray, jint count) {
 
     sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer);
-    jint* atlasMap = env->GetIntArrayElements(atlasMapArray, NULL);
-
-    Caches::getInstance().assetAtlas.init(buffer, atlasMap, count);
-
-    env->ReleaseIntArrayElements(atlasMapArray, atlasMap, 0);
+    jlong* jAtlasMap = env->GetLongArrayElements(atlasMapArray, NULL);
+    Caches::getInstance().assetAtlas.init(buffer, jAtlasMap, count);
+    env->ReleaseLongArrayElements(atlasMapArray, jAtlasMap, 0);
 }
 
 // ----------------------------------------------------------------------------
@@ -216,9 +214,9 @@
 }
 
 static void android_view_GLES20Canvas_detachFunctor(JNIEnv* env,
-        jobject clazz, jlong rendererHandle, jlong functorHandle) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererHandle);
-    Functor* functor = reinterpret_cast<Functor*>(functorHandle);
+        jobject clazz, jlong rendererPtr, jlong functorPtr) {
+    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    Functor* functor = reinterpret_cast<Functor*>(functorPtr);
     renderer->detachFunctor(functor);
 }
 
@@ -1163,7 +1161,7 @@
     { "nInitCaches",        "()Z",             (void*) android_view_GLES20Canvas_initCaches },
     { "nTerminateCaches",   "()V",             (void*) android_view_GLES20Canvas_terminateCaches },
 
-    { "nInitAtlas",         "(Landroid/view/GraphicBuffer;[II)V",
+    { "nInitAtlas",         "(Landroid/view/GraphicBuffer;[JI)V",
             (void*) android_view_GLES20Canvas_initAtlas },
 
     { "nCreateRenderer",    "()J",             (void*) android_view_GLES20Canvas_createRenderer },
diff --git a/core/jni/com_google_android_gles_jni_GLImpl.cpp b/core/jni/com_google_android_gles_jni_GLImpl.cpp
index b3b0049..7975987 100644
--- a/core/jni/com_google_android_gles_jni_GLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_GLImpl.cpp
@@ -129,7 +129,7 @@
             getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void *>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
@@ -4359,7 +4359,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -4460,7 +4460,7 @@
         (GLenum)mode,
         (GLsizei)count,
         (GLenum)type,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
     if (_exception) {
         jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -6099,7 +6099,7 @@
     glNormalPointer(
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -6326,7 +6326,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -6756,7 +6756,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -7196,7 +7196,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -7232,7 +7232,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
diff --git a/core/tests/coretests/src/android/util/JsonReaderTest.java b/core/tests/coretests/src/android/util/JsonReaderTest.java
deleted file mode 100644
index 42b7640..0000000
--- a/core/tests/coretests/src/android/util/JsonReaderTest.java
+++ /dev/null
@@ -1,909 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.Arrays;
-import junit.framework.TestCase;
-
-public final class JsonReaderTest extends TestCase {
-
-    private static final int READER_BUFFER_SIZE = 1024;
-
-    public void testReadArray() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[true, true]"));
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-        assertEquals(true, reader.nextBoolean());
-        reader.endArray();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testReadEmptyArray() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[]"));
-        reader.beginArray();
-        assertFalse(reader.hasNext());
-        reader.endArray();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testReadObject() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader(
-                "{\"a\": \"android\", \"b\": \"banana\"}"));
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-        assertEquals("android", reader.nextString());
-        assertEquals("b", reader.nextName());
-        assertEquals("banana", reader.nextString());
-        reader.endObject();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testReadEmptyObject() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{}"));
-        reader.beginObject();
-        assertFalse(reader.hasNext());
-        reader.endObject();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testSkipObject() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader(
-                "{\"a\": { \"c\": [], \"d\": [true, true, {}] }, \"b\": \"banana\"}"));
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-        reader.skipValue();
-        assertEquals("b", reader.nextName());
-        reader.skipValue();
-        reader.endObject();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testHelloWorld() throws IOException {
-        String json = "{\n" +
-                "   \"hello\": true,\n" +
-                "   \"foo\": [\"world\"]\n" +
-                "}";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginObject();
-        assertEquals("hello", reader.nextName());
-        assertEquals(true, reader.nextBoolean());
-        assertEquals("foo", reader.nextName());
-        reader.beginArray();
-        assertEquals("world", reader.nextString());
-        reader.endArray();
-        reader.endObject();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testNulls() {
-        try {
-            new JsonReader(null);
-            fail();
-        } catch (NullPointerException expected) {
-        }
-    }
-
-    public void testEmptyString() throws IOException {
-        try {
-            new JsonReader(new StringReader("")).beginArray();
-        } catch (IOException expected) {
-        }
-        try {
-            new JsonReader(new StringReader("")).beginObject();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testNoTopLevelObject() throws IOException {
-        try {
-            new JsonReader(new StringReader("true")).nextBoolean();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testCharacterUnescaping() throws IOException {
-        String json = "[\"a\","
-                + "\"a\\\"\","
-                + "\"\\\"\","
-                + "\":\","
-                + "\",\","
-                + "\"\\b\","
-                + "\"\\f\","
-                + "\"\\n\","
-                + "\"\\r\","
-                + "\"\\t\","
-                + "\" \","
-                + "\"\\\\\","
-                + "\"{\","
-                + "\"}\","
-                + "\"[\","
-                + "\"]\","
-                + "\"\\u0000\","
-                + "\"\\u0019\","
-                + "\"\\u20AC\""
-                + "]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginArray();
-        assertEquals("a", reader.nextString());
-        assertEquals("a\"", reader.nextString());
-        assertEquals("\"", reader.nextString());
-        assertEquals(":", reader.nextString());
-        assertEquals(",", reader.nextString());
-        assertEquals("\b", reader.nextString());
-        assertEquals("\f", reader.nextString());
-        assertEquals("\n", reader.nextString());
-        assertEquals("\r", reader.nextString());
-        assertEquals("\t", reader.nextString());
-        assertEquals(" ", reader.nextString());
-        assertEquals("\\", reader.nextString());
-        assertEquals("{", reader.nextString());
-        assertEquals("}", reader.nextString());
-        assertEquals("[", reader.nextString());
-        assertEquals("]", reader.nextString());
-        assertEquals("\0", reader.nextString());
-        assertEquals("\u0019", reader.nextString());
-        assertEquals("\u20AC", reader.nextString());
-        reader.endArray();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testIntegersWithFractionalPartSpecified() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[1.0,1.0,1.0]"));
-        reader.beginArray();
-        assertEquals(1.0, reader.nextDouble());
-        assertEquals(1, reader.nextInt());
-        assertEquals(1L, reader.nextLong());
-    }
-
-    public void testDoubles() throws IOException {
-        String json = "[-0.0,"
-                + "1.0,"
-                + "1.7976931348623157E308,"
-                + "4.9E-324,"
-                + "0.0,"
-                + "-0.5,"
-                + "2.2250738585072014E-308,"
-                + "3.141592653589793,"
-                + "2.718281828459045,"
-                + "\"1.0\","
-                + "\"011.0\","
-                + "\"NaN\","
-                + "\"Infinity\","
-                + "\"-Infinity\""
-                + "]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginArray();
-        assertEquals(-0.0, reader.nextDouble());
-        assertEquals(1.0, reader.nextDouble());
-        assertEquals(1.7976931348623157E308, reader.nextDouble());
-        assertEquals(4.9E-324, reader.nextDouble());
-        assertEquals(0.0, reader.nextDouble());
-        assertEquals(-0.5, reader.nextDouble());
-        assertEquals(2.2250738585072014E-308, reader.nextDouble());
-        assertEquals(3.141592653589793, reader.nextDouble());
-        assertEquals(2.718281828459045, reader.nextDouble());
-        assertEquals(1,0, reader.nextDouble());
-        assertEquals(11.0, reader.nextDouble());
-        assertTrue(Double.isNaN(reader.nextDouble()));
-        assertEquals(Double.POSITIVE_INFINITY, reader.nextDouble());
-        assertEquals(Double.NEGATIVE_INFINITY, reader.nextDouble());
-        reader.endArray();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testLenientDoubles() throws IOException {
-        String json = "["
-                + "011.0,"
-                + "NaN,"
-                + "NAN,"
-                + "Infinity,"
-                + "INFINITY,"
-                + "-Infinity"
-                + "]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals(11.0, reader.nextDouble());
-        assertTrue(Double.isNaN(reader.nextDouble()));
-        try {
-            reader.nextDouble();
-            fail();
-        } catch (NumberFormatException expected) {
-        }
-        assertEquals("NAN", reader.nextString());
-        assertEquals(Double.POSITIVE_INFINITY, reader.nextDouble());
-        try {
-            reader.nextDouble();
-            fail();
-        } catch (NumberFormatException expected) {
-        }
-        assertEquals("INFINITY", reader.nextString());
-        assertEquals(Double.NEGATIVE_INFINITY, reader.nextDouble());
-        reader.endArray();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testBufferBoundary() throws IOException {
-        char[] pad = new char[READER_BUFFER_SIZE - 8];
-        Arrays.fill(pad, '5');
-        String json = "[\"" + new String(pad) + "\",33333]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginArray();
-        assertEquals(JsonToken.STRING, reader.peek());
-        assertEquals(new String(pad), reader.nextString());
-        assertEquals(JsonToken.NUMBER, reader.peek());
-        assertEquals(33333, reader.nextInt());
-    }
-
-    public void testTruncatedBufferBoundary() throws IOException {
-        char[] pad = new char[READER_BUFFER_SIZE - 8];
-        Arrays.fill(pad, '5');
-        String json = "[\"" + new String(pad) + "\",33333";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals(JsonToken.STRING, reader.peek());
-        assertEquals(new String(pad), reader.nextString());
-        assertEquals(JsonToken.NUMBER, reader.peek());
-        assertEquals(33333, reader.nextInt());
-        try {
-            reader.endArray();
-            fail();
-        } catch (IOException e) {
-        }
-    }
-
-    public void testLongestSupportedNumericLiterals() throws IOException {
-        testLongNumericLiterals(READER_BUFFER_SIZE - 1, JsonToken.NUMBER);
-    }
-
-    public void testLongerNumericLiterals() throws IOException {
-        testLongNumericLiterals(READER_BUFFER_SIZE, JsonToken.STRING);
-    }
-
-    private void testLongNumericLiterals(int length, JsonToken expectedToken) throws IOException {
-        char[] longNumber = new char[length];
-        Arrays.fill(longNumber, '9');
-        longNumber[0] = '1';
-        longNumber[1] = '.';
-
-        String json = "[" + new String(longNumber) + "]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals(expectedToken, reader.peek());
-        assertEquals(2.0d, reader.nextDouble());
-        reader.endArray();
-    }
-
-    public void testLongs() throws IOException {
-        String json = "[0,0,0,"
-                + "1,1,1,"
-                + "-1,-1,-1,"
-                + "-9223372036854775808,"
-                + "9223372036854775807,"
-                + "5.0,"
-                + "1.0e2,"
-                + "\"011\","
-                + "\"5.0\","
-                + "\"1.0e2\""
-                + "]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginArray();
-        assertEquals(0L, reader.nextLong());
-        assertEquals(0, reader.nextInt());
-        assertEquals(0.0, reader.nextDouble());
-        assertEquals(1L, reader.nextLong());
-        assertEquals(1, reader.nextInt());
-        assertEquals(1.0, reader.nextDouble());
-        assertEquals(-1L, reader.nextLong());
-        assertEquals(-1, reader.nextInt());
-        assertEquals(-1.0, reader.nextDouble());
-        try {
-            reader.nextInt();
-            fail();
-        } catch (NumberFormatException expected) {
-        }
-        assertEquals(Long.MIN_VALUE, reader.nextLong());
-        try {
-            reader.nextInt();
-            fail();
-        } catch (NumberFormatException expected) {
-        }
-        assertEquals(Long.MAX_VALUE, reader.nextLong());
-        assertEquals(5, reader.nextLong());
-        assertEquals(100, reader.nextLong());
-        assertEquals(11, reader.nextLong());
-        assertEquals(5, reader.nextLong());
-        assertEquals(100, reader.nextLong());
-        reader.endArray();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    /**
-     * This test fails because there's no double for 9223372036854775806, and
-     * our long parsing uses Double.parseDouble() for fractional values.
-     */
-    public void testHighPrecisionLong() throws IOException {
-        String json = "[9223372036854775806.000]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginArray();
-        assertEquals(9223372036854775806L, reader.nextLong());
-        reader.endArray();
-    }
-
-    public void testMatchingValidNumbers() throws IOException {
-        String json = "[-1,99,-0,0,0e1,0e+1,0e-1,0E1,0E+1,0E-1,0.0,1.0,-1.0,1.0e0,1.0e+1,1.0e-1]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginArray();
-        for (int i = 0; i < 16; i++) {
-            assertEquals(JsonToken.NUMBER, reader.peek());
-            reader.nextDouble();
-        }
-        reader.endArray();
-    }
-
-    public void testRecognizingInvalidNumbers() throws IOException {
-        String json = "[-00,00,001,+1,1f,0x,0xf,0x0,0f1,0ee1,1..0,1e0.1,1.-01,1.+1,1.0x,1.0+]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.setLenient(true);
-        reader.beginArray();
-        for (int i = 0; i < 16; i++) {
-            assertEquals(JsonToken.STRING, reader.peek());
-            reader.nextString();
-        }
-        reader.endArray();
-    }
-
-    public void testNonFiniteDouble() throws IOException {
-        String json = "[NaN]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginArray();
-        try {
-            reader.nextDouble();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testNumberWithHexPrefix() throws IOException {
-        String json = "[0x11]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginArray();
-        try {
-            reader.nextLong();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testNumberWithOctalPrefix() throws IOException {
-        String json = "[01]";
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginArray();
-        try {
-            reader.nextInt();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testBooleans() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[true,false]"));
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-        assertEquals(false, reader.nextBoolean());
-        reader.endArray();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testMixedCaseLiterals() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[True,TruE,False,FALSE,NULL,nulL]"));
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-        assertEquals(true, reader.nextBoolean());
-        assertEquals(false, reader.nextBoolean());
-        assertEquals(false, reader.nextBoolean());
-        reader.nextNull();
-        reader.nextNull();
-        reader.endArray();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testMissingValue() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{\"a\":}"));
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-        try {
-            reader.nextString();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testPrematureEndOfInput() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{\"a\":true,"));
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-        assertEquals(true, reader.nextBoolean());
-        try {
-            reader.nextName();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testPrematurelyClosed() throws IOException {
-        try {
-            JsonReader reader = new JsonReader(new StringReader("{\"a\":[]}"));
-            reader.beginObject();
-            reader.close();
-            reader.nextName();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-
-        try {
-            JsonReader reader = new JsonReader(new StringReader("{\"a\":[]}"));
-            reader.close();
-            reader.beginObject();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-
-        try {
-            JsonReader reader = new JsonReader(new StringReader("{\"a\":true}"));
-            reader.beginObject();
-            reader.nextName();
-            reader.peek();
-            reader.close();
-            reader.nextBoolean();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testNextFailuresDoNotAdvance() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{\"a\":true}"));
-        reader.beginObject();
-        try {
-            reader.nextString();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        assertEquals("a", reader.nextName());
-        try {
-            reader.nextName();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        try {
-            reader.beginArray();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        try {
-            reader.endArray();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        try {
-            reader.beginObject();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        try {
-            reader.endObject();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        assertEquals(true, reader.nextBoolean());
-        try {
-            reader.nextString();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        try {
-            reader.nextName();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        try {
-            reader.beginArray();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        try {
-            reader.endArray();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        reader.endObject();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-        reader.close();
-    }
-
-    public void testStringNullIsNotNull() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[\"null\"]"));
-        reader.beginArray();
-        try {
-            reader.nextNull();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testNullLiteralIsNotAString() throws IOException {
-       JsonReader reader = new JsonReader(new StringReader("[null]"));
-        reader.beginArray();
-        try {
-            reader.nextString();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testStrictNameValueSeparator() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{\"a\"=true}"));
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-        try {
-            reader.nextBoolean();
-            fail();
-        } catch (IOException expected) {
-        }
-
-        reader = new JsonReader(new StringReader("{\"a\"=>true}"));
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-        try {
-            reader.nextBoolean();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testLenientNameValueSeparator() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{\"a\"=true}"));
-        reader.setLenient(true);
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-        assertEquals(true, reader.nextBoolean());
-
-        reader = new JsonReader(new StringReader("{\"a\"=>true}"));
-        reader.setLenient(true);
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-        assertEquals(true, reader.nextBoolean());
-    }
-
-    public void testStrictComments() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[// comment \n true]"));
-        reader.beginArray();
-        try {
-            reader.nextBoolean();
-            fail();
-        } catch (IOException expected) {
-        }
-
-        reader = new JsonReader(new StringReader("[# comment \n true]"));
-        reader.beginArray();
-        try {
-            reader.nextBoolean();
-            fail();
-        } catch (IOException expected) {
-        }
-
-        reader = new JsonReader(new StringReader("[/* comment */ true]"));
-        reader.beginArray();
-        try {
-            reader.nextBoolean();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testLenientComments() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[// comment \n true]"));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-
-        reader = new JsonReader(new StringReader("[# comment \n true]"));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-
-        reader = new JsonReader(new StringReader("[/* comment */ true]"));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-    }
-
-    public void testStrictUnquotedNames() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{a:true}"));
-        reader.beginObject();
-        try {
-            reader.nextName();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testLenientUnquotedNames() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{a:true}"));
-        reader.setLenient(true);
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-    }
-
-    public void testStrictSingleQuotedNames() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{'a':true}"));
-        reader.beginObject();
-        try {
-            reader.nextName();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testLenientSingleQuotedNames() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{'a':true}"));
-        reader.setLenient(true);
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-    }
-
-    public void testStrictUnquotedStrings() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[a]"));
-        reader.beginArray();
-        try {
-            reader.nextString();
-            fail();
-        } catch (MalformedJsonException expected) {
-        }
-    }
-
-    public void testLenientUnquotedStrings() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[a]"));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals("a", reader.nextString());
-    }
-
-    public void testStrictSingleQuotedStrings() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("['a']"));
-        reader.beginArray();
-        try {
-            reader.nextString();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testLenientSingleQuotedStrings() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("['a']"));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals("a", reader.nextString());
-    }
-
-    public void testStrictSemicolonDelimitedArray() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[true;true]"));
-        reader.beginArray();
-        try {
-            reader.nextBoolean();
-            reader.nextBoolean();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testLenientSemicolonDelimitedArray() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[true;true]"));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-        assertEquals(true, reader.nextBoolean());
-    }
-
-    public void testStrictSemicolonDelimitedNameValuePair() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{\"a\":true;\"b\":true}"));
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-        try {
-            reader.nextBoolean();
-            reader.nextName();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testLenientSemicolonDelimitedNameValuePair() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("{\"a\":true;\"b\":true}"));
-        reader.setLenient(true);
-        reader.beginObject();
-        assertEquals("a", reader.nextName());
-        assertEquals(true, reader.nextBoolean());
-        assertEquals("b", reader.nextName());
-    }
-
-    public void testStrictUnnecessaryArraySeparators() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[true,,true]"));
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-        try {
-            reader.nextNull();
-            fail();
-        } catch (IOException expected) {
-        }
-
-        reader = new JsonReader(new StringReader("[,true]"));
-        reader.beginArray();
-        try {
-            reader.nextNull();
-            fail();
-        } catch (IOException expected) {
-        }
-
-        reader = new JsonReader(new StringReader("[true,]"));
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-        try {
-            reader.nextNull();
-            fail();
-        } catch (IOException expected) {
-        }
-
-        reader = new JsonReader(new StringReader("[,]"));
-        reader.beginArray();
-        try {
-            reader.nextNull();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testLenientUnnecessaryArraySeparators() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[true,,true]"));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-        reader.nextNull();
-        assertEquals(true, reader.nextBoolean());
-        reader.endArray();
-
-        reader = new JsonReader(new StringReader("[,true]"));
-        reader.setLenient(true);
-        reader.beginArray();
-        reader.nextNull();
-        assertEquals(true, reader.nextBoolean());
-        reader.endArray();
-
-        reader = new JsonReader(new StringReader("[true,]"));
-        reader.setLenient(true);
-        reader.beginArray();
-        assertEquals(true, reader.nextBoolean());
-        reader.nextNull();
-        reader.endArray();
-
-        reader = new JsonReader(new StringReader("[,]"));
-        reader.setLenient(true);
-        reader.beginArray();
-        reader.nextNull();
-        reader.nextNull();
-        reader.endArray();
-    }
-
-    public void testStrictMultipleTopLevelValues() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[] []"));
-        reader.beginArray();
-        reader.endArray();
-        try {
-            reader.peek();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testLenientMultipleTopLevelValues() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[] true {}"));
-        reader.setLenient(true);
-        reader.beginArray();
-        reader.endArray();
-        assertEquals(true, reader.nextBoolean());
-        reader.beginObject();
-        reader.endObject();
-        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
-    }
-
-    public void testStrictTopLevelValueType() {
-        JsonReader reader = new JsonReader(new StringReader("true"));
-        try {
-            reader.nextBoolean();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testLenientTopLevelValueType() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("true"));
-        reader.setLenient(true);
-        assertEquals(true, reader.nextBoolean());
-    }
-
-    public void testStrictNonExecutePrefix() {
-        JsonReader reader = new JsonReader(new StringReader(")]}'\n []"));
-        try {
-            reader.beginArray();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testBomIgnoredAsFirstCharacterOfDocument() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("\ufeff[]"));
-        reader.beginArray();
-        reader.endArray();
-    }
-
-    public void testBomForbiddenAsOtherCharacterInDocument() throws IOException {
-        JsonReader reader = new JsonReader(new StringReader("[\ufeff]"));
-        reader.beginArray();
-        try {
-            reader.endArray();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void testFailWithPosition() throws IOException {
-        testFailWithPosition("Expected literal value at line 6 column 3",
-                "[\n\n\n\n\n0,}]");
-    }
-
-    public void testFailWithPositionIsOffsetByBom() throws IOException {
-        testFailWithPosition("Expected literal value at line 1 column 4",
-                "\ufeff[0,}]");
-    }
-
-    public void testFailWithPositionGreaterThanBufferSize() throws IOException {
-        String spaces = repeat(' ', 8192);
-        testFailWithPosition("Expected literal value at line 6 column 3",
-                "[\n\n" + spaces + "\n\n\n0,}]");
-    }
-
-    private void testFailWithPosition(String message, String json) throws IOException {
-        JsonReader reader = new JsonReader(new StringReader(json));
-        reader.beginArray();
-        reader.nextInt();
-        try {
-            reader.peek();
-            fail();
-        } catch (IOException expected) {
-            assertEquals(message, expected.getMessage());
-        }
-    }
-
-    private String repeat(char c, int count) {
-        char[] array = new char[count];
-        Arrays.fill(array, c);
-        return new String(array);
-    }
-}
diff --git a/core/tests/coretests/src/android/util/JsonWriterTest.java b/core/tests/coretests/src/android/util/JsonWriterTest.java
deleted file mode 100644
index 1239a3c..0000000
--- a/core/tests/coretests/src/android/util/JsonWriterTest.java
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import junit.framework.TestCase;
-
-public final class JsonWriterTest extends TestCase {
-
-    public void testWrongTopLevelType() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        try {
-            jsonWriter.value("a");
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testTwoNames() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginObject();
-        jsonWriter.name("a");
-        try {
-            jsonWriter.name("a");
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testNameWithoutValue() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginObject();
-        jsonWriter.name("a");
-        try {
-            jsonWriter.endObject();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testValueWithoutName() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginObject();
-        try {
-            jsonWriter.value(true);
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testMultipleTopLevelValues() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray().endArray();
-        try {
-            jsonWriter.beginArray();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testBadNestingObject() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.beginObject();
-        try {
-            jsonWriter.endArray();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testBadNestingArray() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.beginArray();
-        try {
-            jsonWriter.endObject();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    public void testNullName() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginObject();
-        try {
-            jsonWriter.name(null);
-            fail();
-        } catch (NullPointerException expected) {
-        }
-    }
-
-    public void testNullStringValue() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginObject();
-        jsonWriter.name("a");
-        jsonWriter.value((String) null);
-        jsonWriter.endObject();
-        assertEquals("{\"a\":null}", stringWriter.toString());
-    }
-
-    public void testNonFiniteDoubles() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        try {
-            jsonWriter.value(Double.NaN);
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-        try {
-            jsonWriter.value(Double.NEGATIVE_INFINITY);
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-        try {
-            jsonWriter.value(Double.POSITIVE_INFINITY);
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-    }
-
-    public void testNonFiniteBoxedDoubles() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        try {
-            jsonWriter.value(new Double(Double.NaN));
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-        try {
-            jsonWriter.value(new Double(Double.NEGATIVE_INFINITY));
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-        try {
-            jsonWriter.value(new Double(Double.POSITIVE_INFINITY));
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-    }
-
-    public void testDoubles() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.value(-0.0);
-        jsonWriter.value(1.0);
-        jsonWriter.value(Double.MAX_VALUE);
-        jsonWriter.value(Double.MIN_VALUE);
-        jsonWriter.value(0.0);
-        jsonWriter.value(-0.5);
-        jsonWriter.value(Double.MIN_NORMAL);
-        jsonWriter.value(Math.PI);
-        jsonWriter.value(Math.E);
-        jsonWriter.endArray();
-        jsonWriter.close();
-        assertEquals("[-0.0,"
-                + "1.0,"
-                + "1.7976931348623157E308,"
-                + "4.9E-324,"
-                + "0.0,"
-                + "-0.5,"
-                + "2.2250738585072014E-308,"
-                + "3.141592653589793,"
-                + "2.718281828459045]", stringWriter.toString());
-    }
-
-    public void testLongs() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.value(0);
-        jsonWriter.value(1);
-        jsonWriter.value(-1);
-        jsonWriter.value(Long.MIN_VALUE);
-        jsonWriter.value(Long.MAX_VALUE);
-        jsonWriter.endArray();
-        jsonWriter.close();
-        assertEquals("[0,"
-                + "1,"
-                + "-1,"
-                + "-9223372036854775808,"
-                + "9223372036854775807]", stringWriter.toString());
-    }
-
-    public void testNumbers() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.value(new BigInteger("0"));
-        jsonWriter.value(new BigInteger("9223372036854775808"));
-        jsonWriter.value(new BigInteger("-9223372036854775809"));
-        jsonWriter.value(new BigDecimal("3.141592653589793238462643383"));
-        jsonWriter.endArray();
-        jsonWriter.close();
-        assertEquals("[0,"
-                + "9223372036854775808,"
-                + "-9223372036854775809,"
-                + "3.141592653589793238462643383]", stringWriter.toString());
-    }
-
-    public void testBooleans() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.value(true);
-        jsonWriter.value(false);
-        jsonWriter.endArray();
-        assertEquals("[true,false]", stringWriter.toString());
-    }
-
-    public void testNulls() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.nullValue();
-        jsonWriter.endArray();
-        assertEquals("[null]", stringWriter.toString());
-    }
-
-    public void testStrings() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.value("a");
-        jsonWriter.value("a\"");
-        jsonWriter.value("\"");
-        jsonWriter.value(":");
-        jsonWriter.value(",");
-        jsonWriter.value("\b");
-        jsonWriter.value("\f");
-        jsonWriter.value("\n");
-        jsonWriter.value("\r");
-        jsonWriter.value("\t");
-        jsonWriter.value(" ");
-        jsonWriter.value("\\");
-        jsonWriter.value("{");
-        jsonWriter.value("}");
-        jsonWriter.value("[");
-        jsonWriter.value("]");
-        jsonWriter.value("\0");
-        jsonWriter.value("\u0019");
-        jsonWriter.endArray();
-        assertEquals("[\"a\","
-                + "\"a\\\"\","
-                + "\"\\\"\","
-                + "\":\","
-                + "\",\","
-                + "\"\\b\","
-                + "\"\\f\","
-                + "\"\\n\","
-                + "\"\\r\","
-                + "\"\\t\","
-                + "\" \","
-                + "\"\\\\\","
-                + "\"{\","
-                + "\"}\","
-                + "\"[\","
-                + "\"]\","
-                + "\"\\u0000\","
-                + "\"\\u0019\"]", stringWriter.toString());
-    }
-
-    public void testUnicodeLineBreaksEscaped() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.value("\u2028 \u2029");
-        jsonWriter.endArray();
-        assertEquals("[\"\\u2028 \\u2029\"]", stringWriter.toString());
-    }
-
-    public void testEmptyArray() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.endArray();
-        assertEquals("[]", stringWriter.toString());
-    }
-
-    public void testEmptyObject() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginObject();
-        jsonWriter.endObject();
-        assertEquals("{}", stringWriter.toString());
-    }
-
-    public void testObjectsInArrays() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginArray();
-        jsonWriter.beginObject();
-        jsonWriter.name("a").value(5);
-        jsonWriter.name("b").value(false);
-        jsonWriter.endObject();
-        jsonWriter.beginObject();
-        jsonWriter.name("c").value(6);
-        jsonWriter.name("d").value(true);
-        jsonWriter.endObject();
-        jsonWriter.endArray();
-        assertEquals("[{\"a\":5,\"b\":false},"
-                + "{\"c\":6,\"d\":true}]", stringWriter.toString());
-    }
-
-    public void testArraysInObjects() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginObject();
-        jsonWriter.name("a");
-        jsonWriter.beginArray();
-        jsonWriter.value(5);
-        jsonWriter.value(false);
-        jsonWriter.endArray();
-        jsonWriter.name("b");
-        jsonWriter.beginArray();
-        jsonWriter.value(6);
-        jsonWriter.value(true);
-        jsonWriter.endArray();
-        jsonWriter.endObject();
-        assertEquals("{\"a\":[5,false],"
-                + "\"b\":[6,true]}", stringWriter.toString());
-    }
-
-    public void testDeepNestingArrays() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        for (int i = 0; i < 20; i++) {
-            jsonWriter.beginArray();
-        }
-        for (int i = 0; i < 20; i++) {
-            jsonWriter.endArray();
-        }
-        assertEquals("[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]", stringWriter.toString());
-    }
-
-    public void testDeepNestingObjects() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginObject();
-        for (int i = 0; i < 20; i++) {
-            jsonWriter.name("a");
-            jsonWriter.beginObject();
-        }
-        for (int i = 0; i < 20; i++) {
-            jsonWriter.endObject();
-        }
-        jsonWriter.endObject();
-        assertEquals("{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":"
-                + "{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{"
-                + "}}}}}}}}}}}}}}}}}}}}}", stringWriter.toString());
-    }
-
-    public void testRepeatedName() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.beginObject();
-        jsonWriter.name("a").value(true);
-        jsonWriter.name("a").value(false);
-        jsonWriter.endObject();
-        // JsonWriter doesn't attempt to detect duplicate names
-        assertEquals("{\"a\":true,\"a\":false}", stringWriter.toString());
-    }
-
-    public void testPrettyPrintObject() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.setIndent("   ");
-
-        jsonWriter.beginObject();
-        jsonWriter.name("a").value(true);
-        jsonWriter.name("b").value(false);
-        jsonWriter.name("c").value(5.0);
-        jsonWriter.name("e").nullValue();
-        jsonWriter.name("f").beginArray();
-        jsonWriter.value(6.0);
-        jsonWriter.value(7.0);
-        jsonWriter.endArray();
-        jsonWriter.name("g").beginObject();
-        jsonWriter.name("h").value(8.0);
-        jsonWriter.name("i").value(9.0);
-        jsonWriter.endObject();
-        jsonWriter.endObject();
-
-        String expected = "{\n"
-                + "   \"a\": true,\n"
-                + "   \"b\": false,\n"
-                + "   \"c\": 5.0,\n"
-                + "   \"e\": null,\n"
-                + "   \"f\": [\n"
-                + "      6.0,\n"
-                + "      7.0\n"
-                + "   ],\n"
-                + "   \"g\": {\n"
-                + "      \"h\": 8.0,\n"
-                + "      \"i\": 9.0\n"
-                + "   }\n"
-                + "}";
-        assertEquals(expected, stringWriter.toString());
-    }
-
-    public void testPrettyPrintArray() throws IOException {
-        StringWriter stringWriter = new StringWriter();
-        JsonWriter jsonWriter = new JsonWriter(stringWriter);
-        jsonWriter.setIndent("   ");
-
-        jsonWriter.beginArray();
-        jsonWriter.value(true);
-        jsonWriter.value(false);
-        jsonWriter.value(5.0);
-        jsonWriter.nullValue();
-        jsonWriter.beginObject();
-        jsonWriter.name("a").value(6.0);
-        jsonWriter.name("b").value(7.0);
-        jsonWriter.endObject();
-        jsonWriter.beginArray();
-        jsonWriter.value(8.0);
-        jsonWriter.value(9.0);
-        jsonWriter.endArray();
-        jsonWriter.endArray();
-
-        String expected = "[\n"
-                + "   true,\n"
-                + "   false,\n"
-                + "   5.0,\n"
-                + "   null,\n"
-                + "   {\n"
-                + "      \"a\": 6.0,\n"
-                + "      \"b\": 7.0\n"
-                + "   },\n"
-                + "   [\n"
-                + "      8.0,\n"
-                + "      9.0\n"
-                + "   ]\n"
-                + "]";
-        assertEquals(expected, stringWriter.toString());
-    }
-}
diff --git a/core/tests/coretests/src/com/android/internal/util/FileRotatorTest.java b/core/tests/coretests/src/com/android/internal/util/FileRotatorTest.java
index 95f0e67..0e3c13a 100644
--- a/core/tests/coretests/src/com/android/internal/util/FileRotatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/FileRotatorTest.java
@@ -43,7 +43,10 @@
 import java.util.Arrays;
 import java.util.Random;
 
+import junit.framework.Assert;
+
 import libcore.io.IoUtils;
+import libcore.io.Libcore;
 
 /**
  * Tests for {@link FileRotator}.
@@ -367,6 +370,16 @@
         assertReadAll(rotate, "bar");
     }
 
+    public void testFileSystemInaccessible() throws Exception {
+        File inaccessibleDir = null;
+        String dirPath = getContext().getFilesDir() + File.separator + "inaccessible";
+        inaccessibleDir = new File(dirPath);
+        final FileRotator rotate = new FileRotator(inaccessibleDir, PREFIX, SECOND_IN_MILLIS, SECOND_IN_MILLIS);
+
+        // rotate should not throw on dir not mkdir-ed (or otherwise inaccessible)
+        rotate.maybeRotate(TEST_TIME);
+    }
+
     private void touch(String... names) throws IOException {
         for (String name : names) {
             final OutputStream out = new FileOutputStream(new File(mBasePath, name));
diff --git a/data/fonts/system_fonts.xml b/data/fonts/system_fonts.xml
index 16e4c7c..549f061b 100644
--- a/data/fonts/system_fonts.xml
+++ b/data/fonts/system_fonts.xml
@@ -75,7 +75,6 @@
             <name>baskerville</name>
             <name>goudy</name>
             <name>fantasy</name>
-            <name>cursive</name>
             <name>ITC Stone Serif</name>
         </nameset>
         <fileset>
@@ -108,4 +107,32 @@
         </fileset>
     </family>
 
+    <family>
+        <nameset>
+            <name>casual</name>
+        </nameset>
+        <fileset>
+            <file>ComingSoon.ttf</file>
+        </fileset>
+    </family>
+
+    <family>
+        <nameset>
+            <name>cursive</name>
+        </nameset>
+        <fileset>
+            <file>DancingScript-Regular.ttf</file>
+            <file>DancingScript-Bold.ttf</file>
+        </fileset>
+    </family>
+
+    <family>
+        <nameset>
+            <name>sans-serif-smallcaps</name>
+        </nameset>
+        <fileset>
+            <file>CarroisGothicSC-Regular.ttf</file>
+        </fileset>
+    </family>
+
 </familyset>
diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd
index 8df1fdf..eabfa60 100644
--- a/docs/html/guide/topics/manifest/activity-element.jd
+++ b/docs/html/guide/topics/manifest/activity-element.jd
@@ -580,7 +580,7 @@
   <a href="#nm"><code>android:name</code></a> attribute.
 
 <p>The system reads this attribute to determine which activity should be started when
-  the use presses the Up button in the action bar. The system can also use this information to
+  the user presses the Up button in the action bar. The system can also use this information to
   synthesize a back stack of activities with {@link android.app.TaskStackBuilder}.</p>
 
 <p>To support API levels 4 - 16, you can also declare the parent activity with a {@code
diff --git a/docs/html/tools/testing/testing_ui.jd b/docs/html/tools/testing/testing_ui.jd
index 701415e..4318a21 100644
--- a/docs/html/tools/testing/testing_ui.jd
+++ b/docs/html/tools/testing/testing_ui.jd
@@ -90,7 +90,7 @@
          alt="User interface of uiautomatorviewer tool" height="327px" id="figure1"/>
 </a>
 <p class="img-caption">
-    <strong>Figure 1.</strong> The {@code uiautomatorviewer} showing the captured interface of a test deviice.
+    <strong>Figure 1.</strong> The {@code uiautomatorviewer} showing the captured interface of a test device.
 </p>
 
 <p>To analyze the UI components of the application that you want to test:</p>
diff --git a/include/android_runtime/AndroidRuntime.h b/include/android_runtime/AndroidRuntime.h
index 0b3ce9a..649f4c3 100644
--- a/include/android_runtime/AndroidRuntime.h
+++ b/include/android_runtime/AndroidRuntime.h
@@ -115,7 +115,7 @@
 
 private:
     static int startReg(JNIEnv* env);
-    void parseExtraOpts(char* extraOptsBuf);
+    void parseExtraOpts(char* extraOptsBuf, const char* quotingArg);
     int startVm(JavaVM** pJavaVM, JNIEnv** pEnv);
 
     Vector<JavaVMOption> mOptions;
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 05411ea..b334aab 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -79,7 +79,7 @@
  * two stretchable slices is exactly the ratio of their corresponding
  * segment lengths.
  *
- * xDivs and yDivs point to arrays of horizontal and vertical pixel
+ * xDivs and yDivs are arrays of horizontal and vertical pixel
  * indices.  The first pair of Divs (in either array) indicate the
  * starting and ending points of the first stretchable segment in that
  * axis. The next pair specifies the next stretchable segment, etc. So
@@ -92,32 +92,31 @@
  * go to xDiv[0] and slices 2, 6 and 10 start at xDiv[1] and end at
  * xDiv[2].
  *
- * The array pointed to by the colors field lists contains hints for
- * each of the regions.  They are ordered according left-to-right and
- * top-to-bottom as indicated above. For each segment that is a solid
- * color the array entry will contain that color value; otherwise it
- * will contain NO_COLOR.  Segments that are completely transparent
- * will always have the value TRANSPARENT_COLOR.
+ * The colors array contains hints for each of the regions. They are
+ * ordered according left-to-right and top-to-bottom as indicated above.
+ * For each segment that is a solid color the array entry will contain
+ * that color value; otherwise it will contain NO_COLOR. Segments that
+ * are completely transparent will always have the value TRANSPARENT_COLOR.
  *
  * The PNG chunk type is "npTc".
  */
 struct Res_png_9patch
 {
-    Res_png_9patch() : wasDeserialized(false), xDivs(NULL),
-                       yDivs(NULL), colors(NULL) { }
+    Res_png_9patch() : wasDeserialized(false), xDivsOffset(0),
+                       yDivsOffset(0), colorsOffset(0) { }
 
     int8_t wasDeserialized;
     int8_t numXDivs;
     int8_t numYDivs;
     int8_t numColors;
 
-    // These tell where the next section of a patch starts.
-    // For example, the first patch includes the pixels from
-    // 0 to xDivs[0]-1 and the second patch includes the pixels
-    // from xDivs[0] to xDivs[1]-1.
-    // Note: allocation/free of these pointers is left to the caller.
-    int32_t* xDivs;
-    int32_t* yDivs;
+    // The offset (from the start of this structure) to the xDivs & yDivs
+    // array for this 9patch. To get a pointer to this array, call
+    // getXDivs or getYDivs. Note that the serialized form for 9patches places
+    // the xDivs, yDivs and colors arrays immediately after the location
+    // of the Res_png_9patch struct.
+    uint32_t xDivsOffset;
+    uint32_t yDivsOffset;
 
     int32_t paddingLeft, paddingRight;
     int32_t paddingTop, paddingBottom;
@@ -129,22 +128,42 @@
         // The 9 patch segment is completely transparent.
         TRANSPARENT_COLOR = 0x00000000
     };
-    // Note: allocation/free of this pointer is left to the caller.
-    uint32_t* colors;
+
+    // The offset (from the start of this structure) to the colors array
+    // for this 9patch.
+    uint32_t colorsOffset;
 
     // Convert data from device representation to PNG file representation.
     void deviceToFile();
     // Convert data from PNG file representation to device representation.
     void fileToDevice();
-    // Serialize/Marshall the patch data into a newly malloc-ed block
-    void* serialize();
-    // Serialize/Marshall the patch data
-    void serialize(void* outData);
+
+    // Serialize/Marshall the patch data into a newly malloc-ed block.
+    static void* serialize(const Res_png_9patch& patchHeader, const int32_t* xDivs,
+                           const int32_t* yDivs, const uint32_t* colors);
+    // Serialize/Marshall the patch data into |outData|.
+    static void serialize(const Res_png_9patch& patchHeader, const int32_t* xDivs,
+                           const int32_t* yDivs, const uint32_t* colors, void* outData);
     // Deserialize/Unmarshall the patch data
-    static Res_png_9patch* deserialize(const void* data);
+    static Res_png_9patch* deserialize(void* data);
     // Compute the size of the serialized data structure
-    size_t serializedSize();
-};
+    size_t serializedSize() const;
+
+    // These tell where the next section of a patch starts.
+    // For example, the first patch includes the pixels from
+    // 0 to xDivs[0]-1 and the second patch includes the pixels
+    // from xDivs[0] to xDivs[1]-1.
+    inline int32_t* getXDivs() const {
+        return reinterpret_cast<int32_t*>(reinterpret_cast<uintptr_t>(this) + xDivsOffset);
+    }
+    inline int32_t* getYDivs() const {
+        return reinterpret_cast<int32_t*>(reinterpret_cast<uintptr_t>(this) + yDivsOffset);
+    }
+    inline uint32_t* getColors() const {
+        return reinterpret_cast<uint32_t*>(reinterpret_cast<uintptr_t>(this) + colorsOffset);
+    }
+
+} __attribute__((packed));
 
 /** ********************************************************************
  *  Base Types
@@ -808,6 +827,19 @@
     uint32_t lastPublicKey;
 };
 
+// The most specific locale can consist of:
+//
+// - a 3 char language code
+// - a 3 char region code prefixed by a 'r'
+// - a 4 char script code prefixed by a 's'
+// - a 8 char variant code prefixed by a 'v'
+//
+// each separated by a single char separator, which sums up to a total of 24
+// chars, (25 include the string terminator) rounded up to 28 to be 4 byte
+// aligned.
+#define RESTABLE_MAX_LOCALE_LEN 28
+
+
 /**
  * Describes a particular resource configuration.
  */
@@ -828,10 +860,42 @@
     
     union {
         struct {
-            // \0\0 means "any".  Otherwise, en, fr, etc.
+            // This field can take three different forms:
+            // - \0\0 means "any".
+            //
+            // - Two 7 bit ascii values interpreted as ISO-639-1 language
+            //   codes ('fr', 'en' etc. etc.). The high bit for both bytes is
+            //   zero.
+            //
+            // - A single 16 bit little endian packed value representing an
+            //   ISO-639-2 3 letter language code. This will be of the form:
+            //
+            //   {1, t, t, t, t, t, s, s, s, s, s, f, f, f, f, f}
+            //
+            //   bit[0, 4] = first letter of the language code
+            //   bit[5, 9] = second letter of the language code
+            //   bit[10, 14] = third letter of the language code.
+            //   bit[15] = 1 always
+            //
+            // For backwards compatibility, languages that have unambiguous
+            // two letter codes are represented in that format.
+            //
+            // The layout is always bigendian irrespective of the runtime
+            // architecture.
             char language[2];
             
-            // \0\0 means "any".  Otherwise, US, CA, etc.
+            // This field can take three different forms:
+            // - \0\0 means "any".
+            //
+            // - Two 7 bit ascii values interpreted as 2 letter region
+            //   codes ('US', 'GB' etc.). The high bit for both bytes is zero.
+            //
+            // - An UN M.49 3 digit region code. For simplicity, these are packed
+            //   in the same manner as the language codes, though we should need
+            //   only 10 bits to represent them, instead of the 15.
+            //
+            // The layout is always bigendian irrespective of the runtime
+            // architecture.
             char country[2];
         };
         uint32_t locale;
@@ -933,7 +997,7 @@
         SDKVERSION_ANY = 0
     };
     
-    enum {
+  enum {
         MINORVERSION_ANY = 0
     };
     
@@ -1006,6 +1070,15 @@
         uint32_t screenSizeDp;
     };
 
+    // The ISO-15924 short name for the script corresponding to this
+    // configuration. (eg. Hant, Latn, etc.). Interpreted in conjunction with
+    // the locale field.
+    char localeScript[4];
+
+    // A single BCP-47 variant subtag. Will vary in length between 5 and 8
+    // chars. Interpreted in conjunction with the locale field.
+    char localeVariant[8];
+
     void copyFromDeviceNoSwap(const ResTable_config& o);
     
     void copyFromDtoH(const ResTable_config& o);
@@ -1063,7 +1136,46 @@
     // settings is the requested settings
     bool match(const ResTable_config& settings) const;
 
-    void getLocale(char str[6]) const;
+    // Get the string representation of the locale component of this
+    // Config. The maximum size of this representation will be
+    // |RESTABLE_MAX_LOCALE_LEN| (including a terminating '\0').
+    //
+    // Example: en-US, en-Latn-US, en-POSIX.
+    void getBcp47Locale(char* out) const;
+
+    // Sets the values of language, region, script and variant to the
+    // well formed BCP-47 locale contained in |in|. The input locale is
+    // assumed to be valid and no validation is performed.
+    void setBcp47Locale(const char* in);
+
+    inline void clearLocale() {
+        locale = 0;
+        memset(localeScript, 0, sizeof(localeScript));
+        memset(localeVariant, 0, sizeof(localeVariant));
+    }
+
+    // Get the 2 or 3 letter language code of this configuration. Trailing
+    // bytes are set to '\0'.
+    size_t unpackLanguage(char language[4]) const;
+    // Get the 2 or 3 letter language code of this configuration. Trailing
+    // bytes are set to '\0'.
+    size_t unpackRegion(char region[4]) const;
+
+    // Sets the language code of this configuration to the first three
+    // chars at |language|.
+    //
+    // If |language| is a 2 letter code, the trailing byte must be '\0' or
+    // the BCP-47 separator '-'.
+    void packLanguage(const char* language);
+    // Sets the region code of this configuration to the first three bytes
+    // at |region|. If |region| is a 2 letter code, the trailing byte must be '\0'
+    // or the BCP-47 separator '-'.
+    void packRegion(const char* region);
+
+    // Returns a positive integer if this config is more specific than |o|
+    // with respect to their locales, a negative integer if |o| is more specific
+    // and 0 if they're equally specific.
+    int isLocaleMoreSpecificThan(const ResTable_config &o) const;
 
     String8 toString() const;
 };
diff --git a/libs/androidfw/Asset.cpp b/libs/androidfw/Asset.cpp
index ce6cc38..589211f 100644
--- a/libs/androidfw/Asset.cpp
+++ b/libs/androidfw/Asset.cpp
@@ -72,7 +72,7 @@
         }
         cur = cur->mNext;
     }
-    
+
     return res;
 }
 
@@ -84,18 +84,18 @@
     mNext = mPrev = NULL;
     if (gTail == NULL) {
         gHead = gTail = this;
-  	} else {
-  	    mPrev = gTail;
-  	    gTail->mNext = this;
-  	    gTail = this;
-  	}
+    } else {
+        mPrev = gTail;
+        gTail->mNext = this;
+        gTail = this;
+    }
     //ALOGI("Creating Asset %p #%d\n", this, gCount);
 }
 
 Asset::~Asset(void)
 {
     AutoMutex _l(gAssetLock);
-	gCount--;
+    gCount--;
     if (gHead == this) {
         gHead = mNext;
     }
@@ -409,7 +409,7 @@
     }
 
     mFileName = fileName != NULL ? strdup(fileName) : NULL;
-    
+
     return NO_ERROR;
 }
 
@@ -538,7 +538,7 @@
         free(mFileName);
         mFileName = NULL;
     }
-    
+
     if (mFp != NULL) {
         // can only be NULL when called from destructor
         // (otherwise we would never return this object)
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 5069958..b4d482a 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -386,17 +386,8 @@
     if (locale) {
         setLocaleLocked(locale);
     } else if (config.language[0] != 0) {
-        char spec[9];
-        spec[0] = config.language[0];
-        spec[1] = config.language[1];
-        if (config.country[0] != 0) {
-            spec[2] = '_';
-            spec[3] = config.country[0];
-            spec[4] = config.country[1];
-            spec[5] = 0;
-        } else {
-            spec[3] = 0;
-        }
+        char spec[RESTABLE_MAX_LOCALE_LEN];
+        config.getBcp47Locale(spec);
         setLocaleLocked(spec);
     } else {
         updateResourceParamsLocked();
@@ -668,20 +659,11 @@
         return;
     }
 
-    size_t llen = mLocale ? strlen(mLocale) : 0;
-    mConfig->language[0] = 0;
-    mConfig->language[1] = 0;
-    mConfig->country[0] = 0;
-    mConfig->country[1] = 0;
-    if (llen >= 2) {
-        mConfig->language[0] = mLocale[0];
-        mConfig->language[1] = mLocale[1];
+    if (mLocale) {
+        mConfig->setBcp47Locale(mLocale);
+    } else {
+        mConfig->clearLocale();
     }
-    if (llen >= 5) {
-        mConfig->country[0] = mLocale[3];
-        mConfig->country[1] = mLocale[4];
-    }
-    mConfig->size = sizeof(*mConfig);
 
     res->setParameters(mConfig);
 }
diff --git a/libs/androidfw/BackupData.cpp b/libs/androidfw/BackupData.cpp
index 4e3b522..2d0f755 100644
--- a/libs/androidfw/BackupData.cpp
+++ b/libs/androidfw/BackupData.cpp
@@ -289,7 +289,7 @@
                     (int)(m_pos - sizeof(m_header)), (int)m_header.type);
             m_status = EINVAL;
     }
-    
+
     return m_status;
 }
 
diff --git a/libs/androidfw/BackupHelpers.cpp b/libs/androidfw/BackupHelpers.cpp
index b8d3f48..ab837ad 100644
--- a/libs/androidfw/BackupHelpers.cpp
+++ b/libs/androidfw/BackupHelpers.cpp
@@ -568,8 +568,8 @@
 
     // [ 108 :   8 ] uid -- ignored in Android format; uids are remapped at restore time
     // [ 116 :   8 ] gid -- ignored in Android format
-    snprintf(buf + 108, 8, "0%lo", s.st_uid);
-    snprintf(buf + 116, 8, "0%lo", s.st_gid);
+    snprintf(buf + 108, 8, "0%lo", (unsigned long)s.st_uid);
+    snprintf(buf + 116, 8, "0%lo", (unsigned long)s.st_gid);
 
     // [ 124 :  12 ] file size in bytes
     if (s.st_size > 077777777777LL) {
@@ -778,7 +778,7 @@
         ALOGW("Could not open file %s -- %s", filename.string(), strerror(errno));
         return errno;
     }
-    
+
     while ((amt = in->ReadEntityData(buf, RESTORE_BUF_SIZE)) > 0) {
         err = write(fd, buf, amt);
         if (err != amt) {
@@ -1083,7 +1083,7 @@
     }
 
     if (readSnapshot.size() != 4) {
-        fprintf(stderr, "readSnapshot should be length 4 is %d\n", readSnapshot.size());
+        fprintf(stderr, "readSnapshot should be length 4 is %zu\n", readSnapshot.size());
         return 1;
     }
 
@@ -1095,8 +1095,8 @@
         if (name != filenames[i] || states[i].modTime_sec != state.modTime_sec
                 || states[i].modTime_nsec != state.modTime_nsec || states[i].mode != state.mode
                 || states[i].size != state.size || states[i].crc32 != states[i].crc32) {
-            fprintf(stderr, "state %d expected={%d/%d, 0x%08x, %04o, 0x%08x, %3d} '%s'\n"
-                            "          actual={%d/%d, 0x%08x, %04o, 0x%08x, %3d} '%s'\n", i,
+            fprintf(stderr, "state %zu expected={%d/%d, 0x%08x, %04o, 0x%08x, %3d} '%s'\n"
+                            "          actual={%d/%d, 0x%08x, %04o, 0x%08x, %3zu} '%s'\n", i,
                     states[i].modTime_sec, states[i].modTime_nsec, states[i].mode, states[i].size,
                     states[i].crc32, name.length(), filenames[i].string(),
                     state.modTime_sec, state.modTime_nsec, state.mode, state.size, state.crc32,
@@ -1230,7 +1230,7 @@
         goto finished;
     }
     if ((int)actualSize != bufSize) {
-        fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08x\n", bufSize,
+        fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08zx\n", bufSize,
                 actualSize);
         err = EINVAL;
         goto finished;
diff --git a/libs/androidfw/CursorWindow.cpp b/libs/androidfw/CursorWindow.cpp
index 0f54edb..2b74a33 100644
--- a/libs/androidfw/CursorWindow.cpp
+++ b/libs/androidfw/CursorWindow.cpp
@@ -1,16 +1,16 @@
 /*
  * Copyright (C) 2006-2007 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 
+ * 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 
+ *      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 
+ * 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.
  */
 
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 8cc98af..652cd4a 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -66,11 +66,6 @@
 // size measured in sizeof(uint32_t)
 #define IDMAP_HEADER_SIZE (ResTable::IDMAP_HEADER_SIZE_BYTES / sizeof(uint32_t))
 
-static void printToLogFunc(int32_t cookie, const char* txt)
-{
-    ALOGV("[cookie=%d] %s", cookie, txt);
-}
-
 // Standard C isspace() is only required to look at the low byte of its input, so
 // produces incorrect results for UTF-16 characters.  For safety's sake, assume that
 // any high-byte UTF-16 code point is not whitespace.
@@ -106,24 +101,29 @@
                 if ((ssize_t)size <= (dataEnd-((const uint8_t*)chunk))) {
                     return NO_ERROR;
                 }
-                ALOGW("%s data size %p extends beyond resource end %p.",
-                     name, (void*)size,
-                     (void*)(dataEnd-((const uint8_t*)chunk)));
+                ALOGW("%s data size 0x%x extends beyond resource end %p.",
+                     name, size, (void*)(dataEnd-((const uint8_t*)chunk)));
                 return BAD_TYPE;
             }
             ALOGW("%s size 0x%x or headerSize 0x%x is not on an integer boundary.",
                  name, (int)size, (int)headerSize);
             return BAD_TYPE;
         }
-        ALOGW("%s size %p is smaller than header size %p.",
-             name, (void*)size, (void*)(int)headerSize);
+        ALOGW("%s size 0x%x is smaller than header size 0x%x.",
+             name, size, headerSize);
         return BAD_TYPE;
     }
-    ALOGW("%s header size %p is too small.",
-         name, (void*)(int)headerSize);
+    ALOGW("%s header size 0x%x is too small.",
+         name, headerSize);
     return BAD_TYPE;
 }
 
+static void fill9patchOffsets(Res_png_9patch* patch) {
+    patch->xDivsOffset = sizeof(Res_png_9patch);
+    patch->yDivsOffset = patch->xDivsOffset + (patch->numXDivs * sizeof(int32_t));
+    patch->colorsOffset = patch->yDivsOffset + (patch->numYDivs * sizeof(int32_t));
+}
+
 inline void Res_value::copyFrom_dtoh(const Res_value& src)
 {
     size = dtohs(src.size);
@@ -134,9 +134,11 @@
 
 void Res_png_9patch::deviceToFile()
 {
+    int32_t* xDivs = getXDivs();
     for (int i = 0; i < numXDivs; i++) {
         xDivs[i] = htonl(xDivs[i]);
     }
+    int32_t* yDivs = getYDivs();
     for (int i = 0; i < numYDivs; i++) {
         yDivs[i] = htonl(yDivs[i]);
     }
@@ -144,6 +146,7 @@
     paddingRight = htonl(paddingRight);
     paddingTop = htonl(paddingTop);
     paddingBottom = htonl(paddingBottom);
+    uint32_t* colors = getColors();
     for (int i=0; i<numColors; i++) {
         colors[i] = htonl(colors[i]);
     }
@@ -151,9 +154,11 @@
 
 void Res_png_9patch::fileToDevice()
 {
+    int32_t* xDivs = getXDivs();
     for (int i = 0; i < numXDivs; i++) {
         xDivs[i] = ntohl(xDivs[i]);
     }
+    int32_t* yDivs = getYDivs();
     for (int i = 0; i < numYDivs; i++) {
         yDivs[i] = ntohl(yDivs[i]);
     }
@@ -161,60 +166,49 @@
     paddingRight = ntohl(paddingRight);
     paddingTop = ntohl(paddingTop);
     paddingBottom = ntohl(paddingBottom);
+    uint32_t* colors = getColors();
     for (int i=0; i<numColors; i++) {
         colors[i] = ntohl(colors[i]);
     }
 }
 
-size_t Res_png_9patch::serializedSize()
+size_t Res_png_9patch::serializedSize() const
 {
     // The size of this struct is 32 bytes on the 32-bit target system
     // 4 * int8_t
     // 4 * int32_t
-    // 3 * pointer
+    // 3 * uint32_t
     return 32
             + numXDivs * sizeof(int32_t)
             + numYDivs * sizeof(int32_t)
             + numColors * sizeof(uint32_t);
 }
 
-void* Res_png_9patch::serialize()
+void* Res_png_9patch::serialize(const Res_png_9patch& patch, const int32_t* xDivs,
+                                const int32_t* yDivs, const uint32_t* colors)
 {
     // Use calloc since we're going to leave a few holes in the data
     // and want this to run cleanly under valgrind
-    void* newData = calloc(1, serializedSize());
-    serialize(newData);
+    void* newData = calloc(1, patch.serializedSize());
+    serialize(patch, xDivs, yDivs, colors, newData);
     return newData;
 }
 
-void Res_png_9patch::serialize(void * outData)
+void Res_png_9patch::serialize(const Res_png_9patch& patch, const int32_t* xDivs,
+                               const int32_t* yDivs, const uint32_t* colors, void* outData)
 {
-    char* data = (char*) outData;
-    memmove(data, &wasDeserialized, 4);     // copy  wasDeserialized, numXDivs, numYDivs, numColors
-    memmove(data + 12, &paddingLeft, 16);   // copy paddingXXXX
+    uint8_t* data = (uint8_t*) outData;
+    memcpy(data, &patch.wasDeserialized, 4);     // copy  wasDeserialized, numXDivs, numYDivs, numColors
+    memcpy(data + 12, &patch.paddingLeft, 16);   // copy paddingXXXX
     data += 32;
 
-    memmove(data, this->xDivs, numXDivs * sizeof(int32_t));
-    data +=  numXDivs * sizeof(int32_t);
-    memmove(data, this->yDivs, numYDivs * sizeof(int32_t));
-    data +=  numYDivs * sizeof(int32_t);
-    memmove(data, this->colors, numColors * sizeof(uint32_t));
-}
+    memcpy(data, xDivs, patch.numXDivs * sizeof(int32_t));
+    data +=  patch.numXDivs * sizeof(int32_t);
+    memcpy(data, yDivs, patch.numYDivs * sizeof(int32_t));
+    data +=  patch.numYDivs * sizeof(int32_t);
+    memcpy(data, colors, patch.numColors * sizeof(uint32_t));
 
-static void deserializeInternal(const void* inData, Res_png_9patch* outData) {
-    char* patch = (char*) inData;
-    if (inData != outData) {
-        memmove(&outData->wasDeserialized, patch, 4);     // copy  wasDeserialized, numXDivs, numYDivs, numColors
-        memmove(&outData->paddingLeft, patch + 12, 4);     // copy  wasDeserialized, numXDivs, numYDivs, numColors
-    }
-    outData->wasDeserialized = true;
-    char* data = (char*)outData;
-    data +=  sizeof(Res_png_9patch);
-    outData->xDivs = (int32_t*) data;
-    data +=  outData->numXDivs * sizeof(int32_t);
-    outData->yDivs = (int32_t*) data;
-    data +=  outData->numYDivs * sizeof(int32_t);
-    outData->colors = (uint32_t*) data;
+    fill9patchOffsets(reinterpret_cast<Res_png_9patch*>(outData));
 }
 
 static bool assertIdmapHeader(const uint32_t* map, size_t sizeBytes)
@@ -318,14 +312,14 @@
     return NO_ERROR;
 }
 
-Res_png_9patch* Res_png_9patch::deserialize(const void* inData)
+Res_png_9patch* Res_png_9patch::deserialize(void* inData)
 {
-    if (sizeof(void*) != sizeof(int32_t)) {
-        ALOGE("Cannot deserialize on non 32-bit system\n");
-        return NULL;
-    }
-    deserializeInternal(inData, (Res_png_9patch*) inData);
-    return (Res_png_9patch*) inData;
+
+    Res_png_9patch* patch = reinterpret_cast<Res_png_9patch*>(inData);
+    patch->wasDeserialized = true;
+    fill9patchOffsets(patch);
+
+    return patch;
 }
 
 // --------------------------------------------------------------------
@@ -1272,7 +1266,7 @@
         const ResXMLTree_node* next = (const ResXMLTree_node*)
             (((const uint8_t*)mCurNode) + dtohl(mCurNode->header.size));
         //ALOGW("Next node: prev=%p, next=%p\n", mCurNode, next);
-        
+
         if (((const uint8_t*)next) >= mTree.mDataEnd) {
             mCurNode = NULL;
             return (mEventCode=END_DOCUMENT);
@@ -1309,7 +1303,7 @@
                      (int)(((const uint8_t*)next)-((const uint8_t*)mTree.mHeader)));
                 continue;
         }
-        
+
         if ((totalSize-headerSize) < minExtSize) {
             ALOGW("Bad XML block: header type 0x%x in node at 0x%x has size %d, need %d\n",
                  (int)dtohs(next->header.type),
@@ -1317,10 +1311,10 @@
                  (int)(totalSize-headerSize), (int)minExtSize);
             return (mEventCode=BAD_DOCUMENT);
         }
-        
+
         //printf("CurNode=%p, CurExt=%p, headerSize=%d, minExtSize=%d\n",
         //       mCurNode, mCurExt, headerSize, minExtSize);
-        
+
         return eventCode;
     } while (true);
 }
@@ -1565,6 +1559,71 @@
     }
 }
 
+/* static */ size_t unpackLanguageOrRegion(const char in[2], const char base,
+        char out[4]) {
+  if (in[0] & 0x80) {
+      // The high bit is "1", which means this is a packed three letter
+      // language code.
+
+      // The smallest 5 bits of the second char are the first alphabet.
+      const uint8_t first = in[1] & 0x1f;
+      // The last three bits of the second char and the first two bits
+      // of the first char are the second alphabet.
+      const uint8_t second = ((in[1] & 0xe0) >> 5) + ((in[0] & 0x03) << 3);
+      // Bits 3 to 7 (inclusive) of the first char are the third alphabet.
+      const uint8_t third = (in[0] & 0x7c) >> 2;
+
+      out[0] = first + base;
+      out[1] = second + base;
+      out[2] = third + base;
+      out[3] = 0;
+
+      return 3;
+  }
+
+  if (in[0]) {
+      memcpy(out, in, 2);
+      memset(out + 2, 0, 2);
+      return 2;
+  }
+
+  memset(out, 0, 4);
+  return 0;
+}
+
+/* static */ void packLanguageOrRegion(const char* in, const char base,
+        char out[2]) {
+  if (in[2] == 0 || in[2] == '-') {
+      out[0] = in[0];
+      out[1] = in[1];
+  } else {
+      uint8_t first = (in[0] - base) & 0x00ef;
+      uint8_t second = (in[1] - base) & 0x00ef;
+      uint8_t third = (in[2] - base) & 0x00ef;
+
+      out[0] = (0x80 | (third << 2) | (second >> 3));
+      out[1] = ((second << 5) | first);
+  }
+}
+
+
+void ResTable_config::packLanguage(const char* language) {
+    packLanguageOrRegion(language, 'a', this->language);
+}
+
+void ResTable_config::packRegion(const char* region) {
+    packLanguageOrRegion(region, '0', this->country);
+}
+
+size_t ResTable_config::unpackLanguage(char language[4]) const {
+    return unpackLanguageOrRegion(this->language, 'a', language);
+}
+
+size_t ResTable_config::unpackRegion(char region[4]) const {
+    return unpackLanguageOrRegion(this->country, '0', region);
+}
+
+
 void ResTable_config::copyFromDtoH(const ResTable_config& o) {
     copyFromDeviceNoSwap(o);
     size = sizeof(ResTable_config);
@@ -1594,10 +1653,30 @@
     screenHeightDp = htods(screenHeightDp);
 }
 
+/* static */ inline int compareLocales(const ResTable_config &l, const ResTable_config &r) {
+    if (l.locale != r.locale) {
+        // NOTE: This is the old behaviour with respect to comparison orders.
+        // The diff value here doesn't make much sense (given our bit packing scheme)
+        // but it's stable, and that's all we need.
+        return l.locale - r.locale;
+    }
+
+    // The language & region are equal, so compare the scripts and variants.
+    int script = memcmp(l.localeScript, r.localeScript, sizeof(l.localeScript));
+    if (script) {
+        return script;
+    }
+
+    // The language, region and script are equal, so compare variants.
+    //
+    // This should happen very infrequently (if at all.)
+    return memcmp(l.localeVariant, r.localeVariant, sizeof(l.localeVariant));
+}
+
 int ResTable_config::compare(const ResTable_config& o) const {
     int32_t diff = (int32_t)(imsi - o.imsi);
     if (diff != 0) return diff;
-    diff = (int32_t)(locale - o.locale);
+    diff = compareLocales(*this, o);
     if (diff != 0) return diff;
     diff = (int32_t)(screenType - o.screenType);
     if (diff != 0) return diff;
@@ -1624,18 +1703,15 @@
     if (mnc != o.mnc) {
         return mnc < o.mnc ? -1 : 1;
     }
-    if (language[0] != o.language[0]) {
-        return language[0] < o.language[0] ? -1 : 1;
+
+    int diff = compareLocales(*this, o);
+    if (diff < 0) {
+        return -1;
     }
-    if (language[1] != o.language[1]) {
-        return language[1] < o.language[1] ? -1 : 1;
+    if (diff > 0) {
+        return 1;
     }
-    if (country[0] != o.country[0]) {
-        return country[0] < o.country[0] ? -1 : 1;
-    }
-    if (country[1] != o.country[1]) {
-        return country[1] < o.country[1] ? -1 : 1;
-    }
+
     if ((screenLayout & MASK_LAYOUTDIR) != (o.screenLayout & MASK_LAYOUTDIR)) {
         return (screenLayout & MASK_LAYOUTDIR) < (o.screenLayout & MASK_LAYOUTDIR) ? -1 : 1;
     }
@@ -1682,7 +1758,6 @@
     int diffs = 0;
     if (mcc != o.mcc) diffs |= CONFIG_MCC;
     if (mnc != o.mnc) diffs |= CONFIG_MNC;
-    if (locale != o.locale) diffs |= CONFIG_LOCALE;
     if (orientation != o.orientation) diffs |= CONFIG_ORIENTATION;
     if (density != o.density) diffs |= CONFIG_DENSITY;
     if (touchscreen != o.touchscreen) diffs |= CONFIG_TOUCHSCREEN;
@@ -1697,9 +1772,44 @@
     if (uiMode != o.uiMode) diffs |= CONFIG_UI_MODE;
     if (smallestScreenWidthDp != o.smallestScreenWidthDp) diffs |= CONFIG_SMALLEST_SCREEN_SIZE;
     if (screenSizeDp != o.screenSizeDp) diffs |= CONFIG_SCREEN_SIZE;
+
+    const int diff = compareLocales(*this, o);
+    if (diff) diffs |= CONFIG_LOCALE;
+
     return diffs;
 }
 
+int ResTable_config::isLocaleMoreSpecificThan(const ResTable_config& o) const {
+    if (locale || o.locale) {
+        if (language[0] != o.language[0]) {
+            if (!language[0]) return -1;
+            if (!o.language[0]) return 1;
+        }
+
+        if (country[0] != o.country[0]) {
+            if (!country[0]) return -1;
+            if (!o.country[0]) return 1;
+        }
+    }
+
+    // There isn't a well specified "importance" order between variants and
+    // scripts. We can't easily tell whether, say "en-Latn-US" is more or less
+    // specific than "en-US-POSIX".
+    //
+    // We therefore arbitrarily decide to give priority to variants over
+    // scripts since it seems more useful to do so. We will consider
+    // "en-US-POSIX" to be more specific than "en-Latn-US".
+
+    const int score = ((localeScript[0] != 0) ? 1 : 0) +
+        ((localeVariant[0] != 0) ? 2 : 0);
+
+    const int oScore = ((o.localeScript[0] != 0) ? 1 : 0) +
+        ((o.localeVariant[0] != 0) ? 2 : 0);
+
+    return score - oScore;
+
+}
+
 bool ResTable_config::isMoreSpecificThan(const ResTable_config& o) const {
     // The order of the following tests defines the importance of one
     // configuration parameter over another.  Those tests first are more
@@ -1717,14 +1827,13 @@
     }
 
     if (locale || o.locale) {
-        if (language[0] != o.language[0]) {
-            if (!language[0]) return false;
-            if (!o.language[0]) return true;
+        const int diff = isLocaleMoreSpecificThan(o);
+        if (diff < 0) {
+            return false;
         }
 
-        if (country[0] != o.country[0]) {
-            if (!country[0]) return false;
-            if (!o.country[0]) return true;
+        if (diff > 0) {
+            return true;
         }
     }
 
@@ -1860,6 +1969,18 @@
             }
         }
 
+        if (localeScript[0] || o.localeScript[0]) {
+            if (localeScript[0] != o.localeScript[0] && requested->localeScript[0]) {
+                return localeScript[0];
+            }
+        }
+
+        if (localeVariant[0] || o.localeVariant[0]) {
+            if (localeVariant[0] != o.localeVariant[0] && requested->localeVariant[0]) {
+                return localeVariant[0];
+            }
+        }
+
         if (screenLayout || o.screenLayout) {
             if (((screenLayout^o.screenLayout) & MASK_LAYOUTDIR) != 0
                     && (requested->screenLayout & MASK_LAYOUTDIR)) {
@@ -2080,17 +2201,23 @@
         }
     }
     if (locale != 0) {
+        // Don't consider the script & variants when deciding matches.
+        //
+        // If we two configs differ only in their script or language, they
+        // can be weeded out in the isMoreSpecificThan test.
         if (language[0] != 0
             && (language[0] != settings.language[0]
                 || language[1] != settings.language[1])) {
             return false;
         }
+
         if (country[0] != 0
             && (country[0] != settings.country[0]
                 || country[1] != settings.country[1])) {
             return false;
         }
     }
+
     if (screenConfig != 0) {
         const int layoutDir = screenLayout&MASK_LAYOUTDIR;
         const int setLayoutDir = settings.screenLayout&MASK_LAYOUTDIR;
@@ -2192,17 +2319,92 @@
     return true;
 }
 
-void ResTable_config::getLocale(char str[6]) const {
-    memset(str, 0, 6);
-    if (language[0]) {
-        str[0] = language[0];
-        str[1] = language[1];
-        if (country[0]) {
-            str[2] = '_';
-            str[3] = country[0];
-            str[4] = country[1];
-        }
+void ResTable_config::getBcp47Locale(char str[RESTABLE_MAX_LOCALE_LEN]) const {
+    memset(str, 0, RESTABLE_MAX_LOCALE_LEN);
+
+    // This represents the "any" locale value, which has traditionally been
+    // represented by the empty string.
+    if (!language[0] && !country[0]) {
+        return;
     }
+
+    size_t charsWritten = 0;
+    if (language[0]) {
+        charsWritten += unpackLanguage(str);
+    }
+
+    if (localeScript[0]) {
+        if (charsWritten) {
+            str[charsWritten++] = '-';
+        }
+        memcpy(str + charsWritten, localeScript, sizeof(localeScript));
+        charsWritten += sizeof(localeScript);
+    }
+
+    if (country[0]) {
+        if (charsWritten) {
+            str[charsWritten++] = '-';
+        }
+        charsWritten += unpackRegion(str + charsWritten);
+    }
+
+    if (localeVariant[0]) {
+        if (charsWritten) {
+            str[charsWritten++] = '-';
+        }
+        memcpy(str + charsWritten, localeVariant, sizeof(localeVariant));
+    }
+}
+
+/* static */ inline bool assignLocaleComponent(ResTable_config* config,
+        const char* start, size_t size) {
+
+  switch (size) {
+       case 0:
+           return false;
+       case 2:
+       case 3:
+           config->language[0] ? config->packRegion(start) : config->packLanguage(start);
+           break;
+       case 4:
+           config->localeScript[0] = toupper(start[0]);
+           for (size_t i = 1; i < 4; ++i) {
+               config->localeScript[i] = tolower(start[i]);
+           }
+           break;
+       case 5:
+       case 6:
+       case 7:
+       case 8:
+           for (size_t i = 0; i < size; ++i) {
+               config->localeVariant[i] = tolower(start[i]);
+           }
+           break;
+       default:
+           return false;
+  }
+
+  return true;
+}
+
+void ResTable_config::setBcp47Locale(const char* in) {
+    locale = 0;
+    memset(localeScript, 0, sizeof(localeScript));
+    memset(localeVariant, 0, sizeof(localeVariant));
+
+    const char* separator = in;
+    const char* start = in;
+    while ((separator = strchr(start, '-')) != NULL) {
+        const size_t size = separator - start;
+        if (!assignLocaleComponent(this, start, size)) {
+            fprintf(stderr, "Invalid BCP-47 locale string: %s", in);
+        }
+
+        start = (separator + 1);
+    }
+
+    const size_t size = in + strlen(in) - start;
+    assignLocaleComponent(this, start, size);
 }
 
 String8 ResTable_config::toString() const {
@@ -2216,14 +2418,10 @@
         if (res.size() > 0) res.append("-");
         res.appendFormat("%dmnc", dtohs(mnc));
     }
-    if (language[0] != 0) {
-        if (res.size() > 0) res.append("-");
-        res.append(language, 2);
-    }
-    if (country[0] != 0) {
-        if (res.size() > 0) res.append("-");
-        res.append(country, 2);
-    }
+    char localeStr[RESTABLE_MAX_LOCALE_LEN];
+    getBcp47Locale(localeStr);
+    res.append(localeStr);
+
     if ((screenLayout&MASK_LAYOUTDIR) != 0) {
         if (res.size() > 0) res.append("-");
         switch (screenLayout&ResTable_config::MASK_LAYOUTDIR) {
@@ -2519,7 +2717,7 @@
             delete types[i];
         }
     }
-    
+
     ResTable* const                 owner;
     const Header* const             header;
     const ResTable_package* const   package;
@@ -2527,7 +2725,7 @@
 
     ResStringPool                   typeStrings;
     ResStringPool                   keyStrings;
-    
+
     const Type* getType(size_t idx) const {
         return idx < types.size() ? types[idx] : NULL;
     }
@@ -2577,18 +2775,18 @@
             bags = NULL;
         }
     }
-    
+
     ResTable* const                 owner;
     String16 const                  name;
     uint32_t const                  id;
     Vector<Package*>                packages;
-    
+
     // This is for finding typeStrings and other common package stuff.
     Package*                        basePackage;
 
     // For quick access.
     size_t                          typeCount;
-    
+
     // Computed attribute bags, first indexed by the type and second
     // by the entry in that type.
     bag_set***                      bags;
@@ -2737,7 +2935,7 @@
 
     //ALOGI("Applying style 0x%08x (force=%d)  theme %p...\n", resID, force, this);
     //dumpToLog();
-    
+
     return NO_ERROR;
 }
 
@@ -2746,7 +2944,7 @@
     //ALOGI("Setting theme %p from theme %p...\n", this, &other);
     //dumpToLog();
     //other.dumpToLog();
-    
+
     if (&mTable == &other.mTable) {
         for (size_t i=0; i<Res_MAXPACKAGE; i++) {
             if (mPackages[i] != NULL) {
@@ -2776,7 +2974,7 @@
 
     //ALOGI("Final theme:");
     //dumpToLog();
-    
+
     return NO_ERROR;
 }
 
@@ -2786,7 +2984,7 @@
     int cnt = 20;
 
     if (outTypeSpecFlags != NULL) *outTypeSpecFlags = 0;
-    
+
     do {
         const ssize_t p = mTable.getResourcePackageIndex(resID);
         const uint32_t t = Res_GETTYPE(resID);
@@ -2860,12 +3058,12 @@
     for (size_t i=0; i<Res_MAXPACKAGE; i++) {
         package_info* pi = mPackages[i];
         if (pi == NULL) continue;
-        
+
         ALOGI("  Package #0x%02x:\n", (int)(i+1));
         for (size_t j=0; j<pi->numTypes; j++) {
             type_info& ti = pi->types[j];
             if (ti.numEntries == 0) continue;
-            
+
             ALOGI("    Type #0x%02x:\n", (int)(j+1));
             for (size_t k=0; k<ti.numEntries; k++) {
                 theme_entry& te = ti.entries[k];
@@ -2927,11 +3125,11 @@
 status_t ResTable::add(ResTable* src)
 {
     mError = src->mError;
-    
+
     for (size_t i=0; i<src->mHeaders.size(); i++) {
         mHeaders.add(src->mHeaders[i]);
     }
-    
+
     for (size_t i=0; i<src->mPackageGroups.size(); i++) {
         PackageGroup* srcPg = src->mPackageGroups[i];
         PackageGroup* pg = new PackageGroup(this, srcPg->name, srcPg->id);
@@ -2942,14 +3140,14 @@
         pg->typeCount = srcPg->typeCount;
         mPackageGroups.add(pg);
     }
-    
+
     memcpy(mPackageMap, src->mPackageMap, sizeof(mPackageMap));
-    
+
     return mError;
 }
 
 status_t ResTable::addInternal(const void* data, size_t size, const int32_t cookie,
-                       Asset* asset, bool copyData, const Asset* idmap)
+                       Asset* /*asset*/, bool copyData, const Asset* idmap)
 {
     if (!data) return NO_ERROR;
     Header* header = new Header(this);
@@ -2973,7 +3171,7 @@
     LOAD_TABLE_NOISY(
         ALOGV("Adding resources to ResTable: data=%p, size=0x%x, cookie=%d, asset=%p, copy=%d "
              "idmap=%p\n", data, size, cookie, asset, copyData, idmap));
-    
+
     if (copyData || notDeviceEndian) {
         header->ownedData = malloc(size);
         if (header->ownedData == NULL) {
@@ -3053,8 +3251,8 @@
             }
             curPackage++;
         } else {
-            ALOGW("Unknown chunk type %p in table at %p.\n",
-                 (void*)(int)(ctype),
+            ALOGW("Unknown chunk type 0x%x in table at %p.\n",
+                 ctype,
                  (void*)(((const uint8_t*)chunk) - ((const uint8_t*)header->header)));
         }
         chunk = (const ResChunk_header*)
@@ -3270,8 +3468,8 @@
 
         if ((dtohs(entry->flags)&entry->FLAG_COMPLEX) != 0) {
             if (!mayBeBag) {
-                ALOGW("Requesting resource %p failed because it is complex\n",
-                     (void*)resID);
+                ALOGW("Requesting resource 0x%x failed because it is complex\n",
+                     resID);
             }
             continue;
         }
@@ -3305,7 +3503,7 @@
             // are identical (diff == 0), or overlay packages will not take effect.
             continue;
         }
-        
+
         bestItem = thisConfig;
         bestValue = item;
         bestPackage = package;
@@ -3375,7 +3573,7 @@
 
 const char16_t* ResTable::valueToString(
     const Res_value* value, size_t stringBlock,
-    char16_t tmpBuffer[TMP_BUFFER_SIZE], size_t* outLen)
+    char16_t /*tmpBuffer*/ [TMP_BUFFER_SIZE], size_t* outLen)
 {
     if (!value) {
         return NULL;
@@ -3398,7 +3596,7 @@
     return err;
 }
 
-void ResTable::unlockBag(const bag_entry* bag) const
+void ResTable::unlockBag(const bag_entry* /*bag*/) const
 {
     //printf("<<< unlockBag %p\n", this);
     mLock.unlock();
@@ -3499,7 +3697,7 @@
     bag_set* set = NULL;
 
     TABLE_NOISY(ALOGI("Building bag: %p\n", (void*)resID));
-    
+
     ResTable_config bestConfig;
     memset(&bestConfig, 0, sizeof(bestConfig));
 
@@ -3546,8 +3744,8 @@
         }
 
         if ((dtohs(entry->flags)&entry->FLAG_COMPLEX) == 0) {
-            ALOGW("Skipping entry %p in package table %d because it is not complex!\n",
-                 (void*)resID, (int)ip);
+            ALOGW("Skipping entry 0x%x in package table %zu because it is not complex!\n",
+                 resID, ip);
             continue;
         }
 
@@ -3565,7 +3763,7 @@
             ? dtohl(((const ResTable_map_entry*)entry)->parent.ident) : 0;
         const uint32_t count = entrySize >= sizeof(ResTable_map_entry)
             ? dtohl(((const ResTable_map_entry*)entry)->count) : 0;
-        
+
         size_t N = count;
 
         TABLE_NOISY(ALOGI("Found map: size=%p parent=%p count=%d\n",
@@ -3609,7 +3807,7 @@
         } else {
             set->typeSpecFlags = -1;
         }
-        
+
         // Now merge in the new attributes...
         ssize_t curOff = offset;
         const ResTable_map* map;
@@ -3872,7 +4070,7 @@
             TABLE_NOISY(printf("Expected type structure not found in package %s for idnex %d\n",
                                String8(group->name).string(), ti));
         }
-        
+
         size_t NTC = typeConfigs->configs.size();
         for (size_t tci=0; tci<NTC; tci++) {
             const ResTable_type* const ty = typeConfigs->configs[tci];
@@ -3888,9 +4086,9 @@
                 if (offset == ResTable_type::NO_ENTRY) {
                     continue;
                 }
-                
+
                 offset += typeOffset;
-                
+
                 if (offset > (dtohl(ty->header.size)-sizeof(ResTable_entry))) {
                     ALOGW("ResTable_entry at %d is beyond type chunk data %d",
                          offset, dtohl(ty->header.size));
@@ -3904,7 +4102,7 @@
                          String8(name, nameLen).string());
                     return 0;
                 }
-                
+
                 const ResTable_entry* const entry = (const ResTable_entry*)
                     (((const uint8_t*)ty) + offset);
                 if (dtohs(entry->size) < sizeof(*entry)) {
@@ -4061,7 +4259,7 @@
     if (*realEnd != 0) {
         return false;
     }
-    
+
     const unit_entry* cur = unitNames;
     while (cur->name) {
         if (len == cur->len && strncmp(cur->name, str, len) == 0) {
@@ -4212,7 +4410,7 @@
             if (neg) {
                 mantissa = (-mantissa) & Res_value::COMPLEX_MANTISSA_MASK;
             }
-            outValue->data |= 
+            outValue->data |=
                 (radix<<Res_value::COMPLEX_RADIX_SHIFT)
                 | (mantissa<<Res_value::COMPLEX_MANTISSA_SHIFT);
             //printf("Input value: %f 0x%016Lx, mult: %f, radix: %d, shift: %d, final: 0x%08x\n",
@@ -4325,7 +4523,7 @@
         // Note: we don't check attrType here because the reference can
         // be to any other type; we just need to count on the client making
         // sure the referenced type is correct.
-        
+
         //printf("Looking up ref: %s\n", String8(s, len).string());
 
         // It's a reference!
@@ -4412,7 +4610,7 @@
             }
         }
     }
-    
+
     if (*s == '#') {
         // It's a color!  Convert to an integer of the form 0xaarrggbb.
         uint32_t color = 0;
@@ -4512,7 +4710,7 @@
         //       String8(package).string(), String8(type).string(),
         //       String8(name).string());
         uint32_t specFlags = 0;
-        uint32_t rid = 
+        uint32_t rid =
             identifierForName(name.string(), name.size(),
                               type.string(), type.size(),
                               package.string(), package.size(), &specFlags);
@@ -4677,7 +4875,7 @@
                             return true;
                         }
                     }
-    
+
                 }
                 bag++;
                 cnt--;
@@ -4976,18 +5174,20 @@
                 const size_t L = type->configs.size();
                 for (size_t l=0; l<L; l++) {
                     const ResTable_type* config = type->configs[l];
-                    const ResTable_config* cfg = &config->config;
+                    ResTable_config cfg;
+                    memset(&cfg, 0, sizeof(ResTable_config));
+                    cfg.copyFromDtoH(config->config);
                     // only insert unique
                     const size_t M = configs->size();
                     size_t m;
                     for (m=0; m<M; m++) {
-                        if (0 == (*configs)[m].compare(*cfg)) {
+                        if (0 == (*configs)[m].compare(cfg)) {
                             break;
                         }
                     }
                     // if we didn't find it
                     if (m == M) {
-                        configs->add(*cfg);
+                        configs->add(cfg);
                     }
                 }
             }
@@ -5002,9 +5202,10 @@
     getConfigurations(&configs);
     ALOGV("called getConfigurations size=%d", (int)configs.size());
     const size_t I = configs.size();
+
+    char locale[RESTABLE_MAX_LOCALE_LEN];
     for (size_t i=0; i<I; i++) {
-        char locale[6];
-        configs[i].getLocale(locale);
+        configs[i].getBcp47Locale(locale);
         const size_t J = locales->size();
         size_t j;
         for (j=0; j<J; j++) {
@@ -5039,43 +5240,43 @@
             entryIndex, (int)allTypes->entryCount);
         return BAD_TYPE;
     }
-        
+
     const ResTable_type* type = NULL;
     uint32_t offset = ResTable_type::NO_ENTRY;
     ResTable_config bestConfig;
     memset(&bestConfig, 0, sizeof(bestConfig)); // make the compiler shut up
-    
+
     const size_t NT = allTypes->configs.size();
     for (size_t i=0; i<NT; i++) {
         const ResTable_type* const thisType = allTypes->configs[i];
         if (thisType == NULL) continue;
-        
+
         ResTable_config thisConfig;
         thisConfig.copyFromDtoH(thisType->config);
 
         TABLE_GETENTRY(ALOGI("Match entry 0x%x in type 0x%x (sz 0x%x): %s\n",
                            entryIndex, typeIndex+1, dtohl(thisType->config.size),
                            thisConfig.toString().string()));
-        
+
         // Check to make sure this one is valid for the current parameters.
         if (config && !thisConfig.match(*config)) {
             TABLE_GETENTRY(ALOGI("Does not match config!\n"));
             continue;
         }
-        
+
         // Check if there is the desired entry in this type.
-        
+
         const uint8_t* const end = ((const uint8_t*)thisType)
             + dtohl(thisType->header.size);
         const uint32_t* const eindex = (const uint32_t*)
             (((const uint8_t*)thisType) + dtohs(thisType->header.headerSize));
-        
+
         uint32_t thisOffset = dtohl(eindex[entryIndex]);
         if (thisOffset == ResTable_type::NO_ENTRY) {
             TABLE_GETENTRY(ALOGI("Skipping because it is not defined!\n"));
             continue;
         }
-        
+
         if (type != NULL) {
             // Check if this one is less specific than the last found.  If so,
             // we will skip it.  We check starting with things we most care
@@ -5085,19 +5286,19 @@
                 continue;
             }
         }
-        
+
         type = thisType;
         offset = thisOffset;
         bestConfig = thisConfig;
         TABLE_GETENTRY(ALOGI("Best entry so far -- using it!\n"));
         if (!config) break;
     }
-    
+
     if (type == NULL) {
         TABLE_GETENTRY(ALOGI("No value found for requested entry!\n"));
         return BAD_INDEX;
     }
-    
+
     offset += dtohl(type->entriesStart);
     TABLE_NOISY(aout << "Looking in resource table " << package->header->header
           << ", typeOff="
@@ -5140,29 +5341,29 @@
         return (mError=err);
     }
 
-    const size_t pkgSize = dtohl(pkg->header.size);
+    const uint32_t pkgSize = dtohl(pkg->header.size);
 
     if (dtohl(pkg->typeStrings) >= pkgSize) {
-        ALOGW("ResTable_package type strings at %p are past chunk size %p.",
-             (void*)dtohl(pkg->typeStrings), (void*)pkgSize);
+        ALOGW("ResTable_package type strings at 0x%x are past chunk size 0x%x.",
+             dtohl(pkg->typeStrings), pkgSize);
         return (mError=BAD_TYPE);
     }
     if ((dtohl(pkg->typeStrings)&0x3) != 0) {
-        ALOGW("ResTable_package type strings at %p is not on an integer boundary.",
-             (void*)dtohl(pkg->typeStrings));
+        ALOGW("ResTable_package type strings at 0x%x is not on an integer boundary.",
+             dtohl(pkg->typeStrings));
         return (mError=BAD_TYPE);
     }
     if (dtohl(pkg->keyStrings) >= pkgSize) {
-        ALOGW("ResTable_package key strings at %p are past chunk size %p.",
-             (void*)dtohl(pkg->keyStrings), (void*)pkgSize);
+        ALOGW("ResTable_package key strings at 0x%x are past chunk size 0x%x.",
+             dtohl(pkg->keyStrings), pkgSize);
         return (mError=BAD_TYPE);
     }
     if ((dtohl(pkg->keyStrings)&0x3) != 0) {
-        ALOGW("ResTable_package key strings at %p is not on an integer boundary.",
-             (void*)dtohl(pkg->keyStrings));
+        ALOGW("ResTable_package key strings at 0x%x is not on an integer boundary.",
+             dtohl(pkg->keyStrings));
         return (mError=BAD_TYPE);
     }
-    
+
     Package* package = NULL;
     PackageGroup* group = NULL;
     uint32_t id = idmap_id != 0 ? idmap_id : dtohl(pkg->id);
@@ -5171,12 +5372,12 @@
     // always loaded alongside their idmaps, but during idmap creation
     // the package is temporarily loaded by itself.
     if (id < 256) {
-    
+
         package = new Package(this, header, pkg);
         if (package == NULL) {
             return (mError=NO_MEMORY);
         }
-        
+
         size_t idx = mPackageMap[id];
         if (idx == 0) {
             idx = mPackageGroups.size()+1;
@@ -5210,7 +5411,7 @@
                 return (mError=err);
             }
             group->basePackage = package;
-            
+
             mPackageMap[id] = (uint8_t)idx;
         } else {
             group = mPackageGroups.itemAt(idx-1);
@@ -5227,10 +5428,10 @@
         return NO_ERROR;
     }
 
-    
+
     // Iterate through all chunks.
     size_t curPackage = 0;
-    
+
     const ResChunk_header* chunk =
         (const ResChunk_header*)(((const uint8_t*)pkg)
                                  + dtohs(pkg->header.headerSize));
@@ -5249,9 +5450,9 @@
             if (err != NO_ERROR) {
                 return (mError=err);
             }
-            
+
             const size_t typeSpecSize = dtohl(typeSpec->header.size);
-            
+
             LOAD_TABLE_NOISY(printf("TypeSpec off %p: type=0x%x, headerSize=0x%x, size=%p\n",
                                     (void*)(base-(const uint8_t*)chunk),
                                     dtohs(typeSpec->header.type),
@@ -5267,12 +5468,12 @@
                      (void*)typeSpecSize);
                 return (mError=BAD_TYPE);
             }
-            
+
             if (typeSpec->id == 0) {
                 ALOGW("ResTable_type has an id of 0.");
                 return (mError=BAD_TYPE);
             }
-            
+
             while (package->types.size() < typeSpec->id) {
                 package->types.add(NULL);
             }
@@ -5288,7 +5489,7 @@
             t->typeSpecFlags = (const uint32_t*)(
                     ((const uint8_t*)typeSpec) + dtohs(typeSpec->header.headerSize));
             t->typeSpec = typeSpec;
-            
+
         } else if (ctype == RES_TABLE_TYPE_TYPE) {
             const ResTable_type* type = (const ResTable_type*)(chunk);
             err = validate_chunk(&type->header, sizeof(*type)-sizeof(ResTable_config)+4,
@@ -5296,9 +5497,9 @@
             if (err != NO_ERROR) {
                 return (mError=err);
             }
-            
-            const size_t typeSize = dtohl(type->header.size);
-            
+
+            const uint32_t typeSize = dtohl(type->header.size);
+
             LOAD_TABLE_NOISY(printf("Type off %p: type=0x%x, headerSize=0x%x, size=%p\n",
                                     (void*)(base-(const uint8_t*)chunk),
                                     dtohs(type->header.type),
@@ -5306,23 +5507,23 @@
                                     (void*)typeSize));
             if (dtohs(type->header.headerSize)+(sizeof(uint32_t)*dtohl(type->entryCount))
                 > typeSize) {
-                ALOGW("ResTable_type entry index to %p extends beyond chunk end %p.",
+                ALOGW("ResTable_type entry index to %p extends beyond chunk end 0x%x.",
                      (void*)(dtohs(type->header.headerSize)
                              +(sizeof(uint32_t)*dtohl(type->entryCount))),
-                     (void*)typeSize);
+                     typeSize);
                 return (mError=BAD_TYPE);
             }
             if (dtohl(type->entryCount) != 0
                 && dtohl(type->entriesStart) > (typeSize-sizeof(ResTable_entry))) {
-                ALOGW("ResTable_type entriesStart at %p extends beyond chunk end %p.",
-                     (void*)dtohl(type->entriesStart), (void*)typeSize);
+                ALOGW("ResTable_type entriesStart at 0x%x extends beyond chunk end 0x%x.",
+                     dtohl(type->entriesStart), typeSize);
                 return (mError=BAD_TYPE);
             }
             if (type->id == 0) {
                 ALOGW("ResTable_type has an id of 0.");
                 return (mError=BAD_TYPE);
             }
-            
+
             while (package->types.size() < type->id) {
                 package->types.add(NULL);
             }
@@ -5335,7 +5536,7 @@
                     (int)dtohl(type->entryCount), (int)t->entryCount);
                 return (mError=BAD_TYPE);
             }
-            
+
             TABLE_GETENTRY(
                 ResTable_config thisConfig;
                 thisConfig.copyFromDtoH(type->config);
@@ -5356,7 +5557,7 @@
     if (group->typeCount == 0) {
         group->typeCount = package->types.size();
     }
-    
+
     return NO_ERROR;
 }
 
@@ -5556,7 +5757,7 @@
             * RADIX_MULTS[(complex>>Res_value::COMPLEX_RADIX_SHIFT)
                             & Res_value::COMPLEX_RADIX_MASK];
     printf("%f", value);
-    
+
     if (!isFraction) {
         switch ((complex>>Res_value::COMPLEX_UNIT_SHIFT)&Res_value::COMPLEX_UNIT_MASK) {
             case Res_value::COMPLEX_UNIT_PX: printf("px"); break;
@@ -5631,7 +5832,7 @@
             } else {
                 printf("(string) null\n");
             }
-        } 
+        }
     } else if (value.dataType == Res_value::TYPE_FLOAT) {
         printf("(float) %g\n", *(const float*)&value.data);
     } else if (value.dataType == Res_value::TYPE_DIMENSION) {
@@ -5663,9 +5864,9 @@
         printf("mError=0x%x (%s)\n", mError, strerror(mError));
     }
 #if 0
-    printf("mParams=%c%c-%c%c,\n",
-            mParams.language[0], mParams.language[1],
-            mParams.country[0], mParams.country[1]);
+    char localeStr[RESTABLE_MAX_LOCALE_LEN];
+    mParams.getBcp47Locale(localeStr);
+    printf("mParams=%s,\n" localeStr);
 #endif
     size_t pgCount = mPackageGroups.size();
     printf("Package Groups (%d)\n", (int)pgCount);
@@ -5674,7 +5875,7 @@
         printf("Package Group %d id=%d packageCount=%d name=%s\n",
                 (int)pgIndex, pg->id, (int)pg->packages.size(),
                 String8(pg->name).string());
-        
+
         size_t pkgCount = pg->packages.size();
         for (size_t pkgIndex=0; pkgIndex<pkgCount; pkgIndex++) {
             const Package* pkg = pg->packages[pkgIndex];
@@ -5732,26 +5933,26 @@
                     size_t entryCount = dtohl(type->entryCount);
                     uint32_t entriesStart = dtohl(type->entriesStart);
                     if ((entriesStart&0x3) != 0) {
-                        printf("      NON-INTEGER ResTable_type entriesStart OFFSET: %p\n", (void*)entriesStart);
+                        printf("      NON-INTEGER ResTable_type entriesStart OFFSET: 0x%x\n", entriesStart);
                         continue;
                     }
                     uint32_t typeSize = dtohl(type->header.size);
                     if ((typeSize&0x3) != 0) {
-                        printf("      NON-INTEGER ResTable_type header.size: %p\n", (void*)typeSize);
+                        printf("      NON-INTEGER ResTable_type header.size: 0x%x\n", typeSize);
                         continue;
                     }
                     for (size_t entryIndex=0; entryIndex<entryCount; entryIndex++) {
-                        
+
                         const uint8_t* const end = ((const uint8_t*)type)
                             + dtohl(type->header.size);
                         const uint32_t* const eindex = (const uint32_t*)
                             (((const uint8_t*)type) + dtohs(type->header.headerSize));
-                        
+
                         uint32_t thisOffset = dtohl(eindex[entryIndex]);
                         if (thisOffset == ResTable_type::NO_ENTRY) {
                             continue;
                         }
-                        
+
                         uint32_t resID = (0xff000000 & ((pkg->package->id)<<24))
                                     | (0x00ff0000 & ((typeIndex+1)<<16))
                                     | (0x0000ffff & (entryIndex));
@@ -5776,36 +5977,34 @@
                             printf("        INVALID RESOURCE 0x%08x: ", resID);
                         }
                         if ((thisOffset&0x3) != 0) {
-                            printf("NON-INTEGER OFFSET: %p\n", (void*)thisOffset);
+                            printf("NON-INTEGER OFFSET: 0x%x\n", thisOffset);
                             continue;
                         }
                         if ((thisOffset+sizeof(ResTable_entry)) > typeSize) {
-                            printf("OFFSET OUT OF BOUNDS: %p+%p (size is %p)\n",
-                                   (void*)entriesStart, (void*)thisOffset,
-                                   (void*)typeSize);
+                            printf("OFFSET OUT OF BOUNDS: 0x%x+0x%x (size is 0x%x)\n",
+                                   entriesStart, thisOffset, typeSize);
                             continue;
                         }
-                        
+
                         const ResTable_entry* ent = (const ResTable_entry*)
                             (((const uint8_t*)type) + entriesStart + thisOffset);
                         if (((entriesStart + thisOffset)&0x3) != 0) {
-                            printf("NON-INTEGER ResTable_entry OFFSET: %p\n",
-                                 (void*)(entriesStart + thisOffset));
+                            printf("NON-INTEGER ResTable_entry OFFSET: 0x%x\n",
+                                 (entriesStart + thisOffset));
                             continue;
                         }
-                        
-                        uint16_t esize = dtohs(ent->size);
+
+                        uintptr_t esize = dtohs(ent->size);
                         if ((esize&0x3) != 0) {
-                            printf("NON-INTEGER ResTable_entry SIZE: %p\n", (void*)esize);
+                            printf("NON-INTEGER ResTable_entry SIZE: 0x%x\n", esize);
                             continue;
                         }
                         if ((thisOffset+esize) > typeSize) {
-                            printf("ResTable_entry OUT OF BOUNDS: %p+%p+%p (size is %p)\n",
-                                   (void*)entriesStart, (void*)thisOffset,
-                                   (void*)esize, (void*)typeSize);
+                            printf("ResTable_entry OUT OF BOUNDS: 0x%x+0x%x+0x%x (size is 0x%x)\n",
+                                   entriesStart, thisOffset, esize, typeSize);
                             continue;
                         }
-                            
+
                         const Res_value* valuePtr = NULL;
                         const ResTable_map_entry* bagPtr = NULL;
                         Res_value value;
@@ -5820,12 +6019,12 @@
                                    (int)value.dataType, (int)value.data,
                                    (int)value.size, (int)value.res0);
                         }
-                        
+
                         if ((dtohs(ent->flags)&ResTable_entry::FLAG_PUBLIC) != 0) {
                             printf(" (PUBLIC)");
                         }
                         printf("\n");
-                        
+
                         if (inclValues) {
                             if (valuePtr != NULL) {
                                 printf("          ");
diff --git a/libs/androidfw/ZipUtils.cpp b/libs/androidfw/ZipUtils.cpp
index e9ac2fe..6fa0f14 100644
--- a/libs/androidfw/ZipUtils.cpp
+++ b/libs/androidfw/ZipUtils.cpp
@@ -127,7 +127,7 @@
             goto z_bail;
         }
 
-		/* output buffer holds all, so no need to write the output */
+        /* output buffer holds all, so no need to write the output */
     } while (zerr == Z_OK);
 
     assert(zerr == Z_STREAM_END);       /* other errors should've been caught */
@@ -197,7 +197,7 @@
     {
     }
 
-    long read(unsigned char** nextBuffer, long readSize) {
+    long read(unsigned char** nextBuffer, long /*readSize*/) {
         if (!mBufferReturned) {
             mBufferReturned = true;
             *nextBuffer = mInput;
diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk
index 3c55375..977ba80 100644
--- a/libs/androidfw/tests/Android.mk
+++ b/libs/androidfw/tests/Android.mk
@@ -5,7 +5,8 @@
 # Build the unit tests.
 test_src_files := \
     ObbFile_test.cpp \
-    ZipUtils_test.cpp
+    ZipUtils_test.cpp \
+    ResourceTypes_test.cpp
 
 shared_libraries := \
     libandroidfw \
diff --git a/libs/androidfw/tests/ResourceTypes_test.cpp b/libs/androidfw/tests/ResourceTypes_test.cpp
new file mode 100644
index 0000000..4888b4a
--- /dev/null
+++ b/libs/androidfw/tests/ResourceTypes_test.cpp
@@ -0,0 +1,185 @@
+/*
+ * 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/Log.h>
+#include <utils/String8.h>
+
+#include <gtest/gtest.h>
+namespace android {
+
+TEST(ResourceTypesTest, ResourceConfig_packAndUnpack2LetterLanguage) {
+     ResTable_config config;
+     config.packLanguage("en");
+
+     EXPECT_EQ('e', config.language[0]);
+     EXPECT_EQ('n', config.language[1]);
+
+     char out[4] = { 1, 1, 1, 1};
+     config.unpackLanguage(out);
+     EXPECT_EQ('e', out[0]);
+     EXPECT_EQ('n', out[1]);
+     EXPECT_EQ(0, out[2]);
+     EXPECT_EQ(0, out[3]);
+
+     memset(out, 1, sizeof(out));
+     config.locale = 0;
+     config.unpackLanguage(out);
+     EXPECT_EQ(0, out[0]);
+     EXPECT_EQ(0, out[1]);
+     EXPECT_EQ(0, out[2]);
+     EXPECT_EQ(0, out[3]);
+}
+
+TEST(ResourceTypesTest, ResourceConfig_packAndUnpack2LetterRegion) {
+     ResTable_config config;
+     config.packRegion("US");
+
+     EXPECT_EQ('U', config.country[0]);
+     EXPECT_EQ('S', config.country[1]);
+
+     char out[4] = { 1, 1, 1, 1};
+     config.unpackRegion(out);
+     EXPECT_EQ('U', out[0]);
+     EXPECT_EQ('S', out[1]);
+     EXPECT_EQ(0, out[2]);
+     EXPECT_EQ(0, out[3]);
+}
+
+TEST(ResourceTypesTest, ResourceConfig_packAndUnpack3LetterLanguage) {
+     ResTable_config config;
+     config.packLanguage("eng");
+
+     // 1-00110-01 101-00100
+     EXPECT_EQ(0x99, config.language[0]);
+     EXPECT_EQ(0xa4, config.language[1]);
+
+     char out[4] = { 1, 1, 1, 1};
+     config.unpackLanguage(out);
+     EXPECT_EQ('e', out[0]);
+     EXPECT_EQ('n', out[1]);
+     EXPECT_EQ('g', out[2]);
+     EXPECT_EQ(0, out[3]);
+}
+
+TEST(ResourceTypesTest, ResourceConfig_packAndUnpack3LetterRegion) {
+     ResTable_config config;
+     config.packRegion("419");
+
+     char out[4] = { 1, 1, 1, 1};
+     config.unpackRegion(out);
+
+     EXPECT_EQ('4', out[0]);
+     EXPECT_EQ('1', out[1]);
+     EXPECT_EQ('9', out[2]);
+}
+
+/* static */ void fillIn(const char* lang, const char* country,
+        const char* script, const char* variant, ResTable_config* out) {
+     memset(out, 0, sizeof(ResTable_config));
+     if (lang != NULL) {
+         out->packLanguage(lang);
+     }
+
+     if (country != NULL) {
+         out->packRegion(country);
+     }
+
+     if (script != NULL) {
+         memcpy(out->localeScript, script, 4);
+     }
+
+     if (variant != NULL) {
+         memcpy(out->localeVariant, variant, strlen(variant));
+     }
+}
+
+TEST(ResourceTypesTest, IsMoreSpecificThan) {
+    ResTable_config l;
+    ResTable_config r;
+
+    fillIn("en", NULL, NULL, NULL, &l);
+    fillIn(NULL, NULL, NULL, NULL, &r);
+
+    EXPECT_TRUE(l.isMoreSpecificThan(r));
+    EXPECT_FALSE(r.isMoreSpecificThan(l));
+
+    fillIn("eng", NULL, NULL, NULL, &l);
+    EXPECT_TRUE(l.isMoreSpecificThan(r));
+    EXPECT_FALSE(r.isMoreSpecificThan(l));
+
+    fillIn("eng", "419", NULL, NULL, &r);
+    EXPECT_FALSE(l.isMoreSpecificThan(r));
+    EXPECT_TRUE(r.isMoreSpecificThan(l));
+
+    fillIn("en", NULL, NULL, NULL, &l);
+    fillIn("en", "US", NULL, NULL, &r);
+    EXPECT_FALSE(l.isMoreSpecificThan(r));
+    EXPECT_TRUE(r.isMoreSpecificThan(l));
+
+    fillIn("en", "US", NULL, NULL, &l);
+    fillIn("en", "US", "Latn", NULL, &r);
+    EXPECT_FALSE(l.isMoreSpecificThan(r));
+    EXPECT_TRUE(r.isMoreSpecificThan(l));
+
+    fillIn("en", "US", NULL, NULL, &l);
+    fillIn("en", "US", NULL, "POSIX", &r);
+    EXPECT_FALSE(l.isMoreSpecificThan(r));
+    EXPECT_TRUE(r.isMoreSpecificThan(l));
+
+    fillIn("en", "US", "Latn", NULL, &l);
+    fillIn("en", "US", NULL, "POSIX", &r);
+    EXPECT_FALSE(l.isMoreSpecificThan(r));
+    EXPECT_TRUE(r.isMoreSpecificThan(l));
+}
+
+TEST(ResourceTypesTest, setLocale) {
+    ResTable_config test;
+    test.setBcp47Locale("en-US");
+    EXPECT_EQ('e', test.language[0]);
+    EXPECT_EQ('n', test.language[1]);
+    EXPECT_EQ('U', test.country[0]);
+    EXPECT_EQ('S', test.country[1]);
+    EXPECT_EQ(0, test.localeScript[0]);
+    EXPECT_EQ(0, test.localeVariant[0]);
+
+    test.setBcp47Locale("eng-419");
+    char out[4] = { 1, 1, 1, 1};
+    test.unpackLanguage(out);
+    EXPECT_EQ('e', out[0]);
+    EXPECT_EQ('n', out[1]);
+    EXPECT_EQ('g', out[2]);
+    EXPECT_EQ(0, out[3]);
+    memset(out, 1, 4);
+    test.unpackRegion(out);
+    EXPECT_EQ('4', out[0]);
+    EXPECT_EQ('1', out[1]);
+    EXPECT_EQ('9', out[2]);
+
+
+    test.setBcp47Locale("en-Latn-419");
+    memset(out, 1, 4);
+    EXPECT_EQ('e', test.language[0]);
+    EXPECT_EQ('n', test.language[1]);
+
+    EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4));
+    test.unpackRegion(out);
+    EXPECT_EQ('4', out[0]);
+    EXPECT_EQ('1', out[1]);
+    EXPECT_EQ('9', out[2]);
+}
+
+}  // namespace android.
diff --git a/libs/hwui/AssetAtlas.cpp b/libs/hwui/AssetAtlas.cpp
index eb8bb9f..e8c3d3c 100644
--- a/libs/hwui/AssetAtlas.cpp
+++ b/libs/hwui/AssetAtlas.cpp
@@ -28,7 +28,7 @@
 // Lifecycle
 ///////////////////////////////////////////////////////////////////////////////
 
-void AssetAtlas::init(sp<GraphicBuffer> buffer, int* map, int count) {
+void AssetAtlas::init(sp<GraphicBuffer> buffer, int64_t* map, int count) {
     if (mImage) {
         return;
     }
@@ -108,14 +108,19 @@
 /**
  * TODO: This method does not take the rotation flag into account
  */
-void AssetAtlas::createEntries(Caches& caches, int* map, int count) {
+void AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) {
     const float width = float(mTexture->width);
     const float height = float(mTexture->height);
 
     for (int i = 0; i < count; ) {
-        SkBitmap* bitmap = (SkBitmap*) map[i++];
-        int x = map[i++];
-        int y = map[i++];
+        SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(map[i++]);
+        // NOTE: We're converting from 64 bit signed values to 32 bit
+        // signed values. This is guaranteed to be safe because the "x"
+        // and "y" coordinate values are guaranteed to be representable
+        // with 32 bits. The array is 64 bits wide so that it can carry
+        // pointers on 64 bit architectures.
+        const int x = static_cast<int>(map[i++]);
+        const int y = static_cast<int>(map[i++]);
         bool rotated = map[i++] > 0;
 
         // Bitmaps should never be null, we're just extra paranoid
diff --git a/libs/hwui/AssetAtlas.h b/libs/hwui/AssetAtlas.h
index a28efc6..163bdbc 100644
--- a/libs/hwui/AssetAtlas.h
+++ b/libs/hwui/AssetAtlas.h
@@ -121,7 +121,7 @@
      * initialized. To re-initialize the atlas, you must
      * first call terminate().
      */
-    ANDROID_API void init(sp<GraphicBuffer> buffer, int* map, int count);
+    ANDROID_API void init(sp<GraphicBuffer> buffer, int64_t* map, int count);
 
     /**
      * Destroys the atlas texture. This object can be
@@ -176,7 +176,7 @@
     }
 
 private:
-    void createEntries(Caches& caches, int* map, int count);
+    void createEntries(Caches& caches, int64_t* map, int count);
 
     Texture* mTexture;
     Image* mImage;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 326805a..842e028 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1444,7 +1444,7 @@
                 DeferredDisplayList::kOpBatch_Text :
                 DeferredDisplayList::kOpBatch_ColorText;
 
-        deferInfo.mergeId = (mergeid_t)mPaint->getColor();
+        deferInfo.mergeId = reinterpret_cast<mergeid_t>(mPaint->getColor());
 
         // don't merge decorated text - the decorations won't draw in order
         bool noDecorations = !(mPaint->getFlags() & (SkPaint::kUnderlineText_Flag |
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index 9b023f9..b2148b0 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -57,7 +57,7 @@
     if (vertices) return vertices;
 
     int8_t emptyQuads = 0;
-    mColors = patch->colors;
+    mColors = patch->getColors();
 
     const int8_t numColors = patch->numColors;
     if (uint8_t(numColors) < sizeof(uint32_t) * 4) {
@@ -79,8 +79,8 @@
     TextureVertex* tempVertices = new TextureVertex[maxVertices];
     TextureVertex* vertex = tempVertices;
 
-    const int32_t* xDivs = patch->xDivs;
-    const int32_t* yDivs = patch->yDivs;
+    const int32_t* xDivs = patch->getXDivs();
+    const int32_t* yDivs = patch->getYDivs();
 
     const uint32_t xStretchCount = (xCount + 1) >> 1;
     const uint32_t yStretchCount = (yCount + 1) >> 1;
diff --git a/libs/hwui/Patch.h b/libs/hwui/Patch.h
index 763a785..b5e8838 100644
--- a/libs/hwui/Patch.h
+++ b/libs/hwui/Patch.h
@@ -66,7 +66,7 @@
     void generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
             float u1, float v1, float u2, float v2, uint32_t& quadCount);
 
-    uint32_t* mColors;
+    const uint32_t* mColors;
     UvMapper mUvMapper;
 }; // struct Patch
 
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
index dc0d98c..8a44604 100644
--- a/libs/hwui/PatchCache.cpp
+++ b/libs/hwui/PatchCache.cpp
@@ -129,7 +129,11 @@
         Mutex::Autolock _l(mLock);
         size_t count = mGarbage.size();
         for (size_t i = 0; i < count; i++) {
-            remove(patchesToRemove, mGarbage[i]);
+            Res_png_9patch* patch = mGarbage[i];
+            remove(patchesToRemove, patch);
+            // A Res_png_9patch is actually an array of byte that's larger
+            // than sizeof(Res_png_9patch). It must be freed as an array.
+            delete[] (int8_t*) patch;
         }
         mGarbage.clear();
     }
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 5df6408..cf8adf8 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -395,7 +395,9 @@
         Mutex::Autolock l(mLock);
         size_t count = mGarbage.size();
         for (size_t i = 0; i < count; i++) {
-            remove(pathsToRemove, mGarbage.itemAt(i));
+            const path_pair_t& pair = mGarbage.itemAt(i);
+            remove(pathsToRemove, pair);
+            delete pair.getFirst();
         }
         mGarbage.clear();
     }
diff --git a/libs/hwui/PixelBuffer.cpp b/libs/hwui/PixelBuffer.cpp
index 36e89c6..5b642b9 100644
--- a/libs/hwui/PixelBuffer.cpp
+++ b/libs/hwui/PixelBuffer.cpp
@@ -151,7 +151,7 @@
     mCaches.bindPixelBuffer(mBuffer);
     unmap();
     glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat,
-            GL_UNSIGNED_BYTE, (void*) offset);
+            GL_UNSIGNED_BYTE, reinterpret_cast<void*>(offset));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 3f77021..d276a29 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -213,8 +213,9 @@
         // If we're not tracking this resource, just delete it
         if (Caches::hasInstance()) {
             Caches::getInstance().pathCache.removeDeferred(resource);
+        } else {
+            delete resource;
         }
-        delete resource;
         return;
     }
     ref->destroyed = true;
@@ -235,8 +236,9 @@
         // If we're not tracking this resource, just delete it
         if (Caches::hasInstance()) {
             Caches::getInstance().textureCache.removeDeferred(resource);
+        } else {
+            delete resource;
         }
-        delete resource;
         return;
     }
     ref->destroyed = true;
@@ -292,13 +294,14 @@
     ssize_t index = mCache->indexOfKey(resource);
     ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
     if (ref == NULL) {
+        // If we're not tracking this resource, just delete it
         if (Caches::hasInstance()) {
             Caches::getInstance().patchCache.removeDeferred(resource);
+        } else {
+            // A Res_png_9patch is actually an array of byte that's larger
+            // than sizeof(Res_png_9patch). It must be freed as an array.
+            delete[] (int8_t*) resource;
         }
-        // If we're not tracking this resource, just delete it
-        // A Res_png_9patch is actually an array of byte that's larger
-        // than sizeof(Res_png_9patch). It must be freed as an array.
-        delete[] (int8_t*) resource;
         return;
     }
     ref->destroyed = true;
@@ -355,16 +358,18 @@
                 SkBitmap* bitmap = (SkBitmap*) resource;
                 if (Caches::hasInstance()) {
                     Caches::getInstance().textureCache.removeDeferred(bitmap);
+                } else {
+                    delete bitmap;
                 }
-                delete bitmap;
             }
             break;
             case kPath: {
                 SkPath* path = (SkPath*) resource;
                 if (Caches::hasInstance()) {
                     Caches::getInstance().pathCache.removeDeferred(path);
+                } else {
+                    delete path;
                 }
-                delete path;
             }
             break;
             case kShader: {
@@ -380,11 +385,12 @@
             case kNinePatch: {
                 if (Caches::hasInstance()) {
                     Caches::getInstance().patchCache.removeDeferred((Res_png_9patch*) resource);
+                } else {
+                    // A Res_png_9patch is actually an array of byte that's larger
+                    // than sizeof(Res_png_9patch). It must be freed as an array.
+                    int8_t* patch = (int8_t*) resource;
+                    delete[] patch;
                 }
-                // A Res_png_9patch is actually an array of byte that's larger
-                // than sizeof(Res_png_9patch). It must be freed as an array.
-                int8_t* patch = (int8_t*) resource;
-                delete[] patch;
             }
             break;
             case kLayer: {
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index ed0a79a..ad235a9 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -184,7 +184,9 @@
     Mutex::Autolock _l(mLock);
     size_t count = mGarbage.size();
     for (size_t i = 0; i < count; i++) {
-        mCache.remove(mGarbage.itemAt(i));
+        SkBitmap* bitmap = mGarbage.itemAt(i);
+        mCache.remove(bitmap);
+        delete bitmap;
     }
     mGarbage.clear();
 }
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index 705de88..543cb6c 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -556,7 +556,7 @@
         return JNI_FALSE;
     }
 
-    size_t numSubSamples = size / sizeof(size_t);
+    size_t numSubSamples = size / sizeof(int32_t);
 
     if (numSubSamples == 0) {
         return JNI_FALSE;
@@ -566,7 +566,7 @@
     jboolean isCopy;
     jint *dst = env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
     for (size_t i = 0; i < numSubSamples; ++i) {
-        dst[i] = ((const size_t *)data)[i];
+        dst[i] = ((const int32_t *)data)[i];
     }
     env->ReleaseIntArrayElements(numBytesOfEncryptedDataObj, dst, 0);
     dst = NULL;
@@ -583,7 +583,7 @@
         jboolean isCopy;
         jint *dst = env->GetIntArrayElements(numBytesOfPlainDataObj, &isCopy);
         for (size_t i = 0; i < numSubSamples; ++i) {
-            dst[i] = ((const size_t *)data)[i];
+            dst[i] = ((const int32_t *)data)[i];
         }
         env->ReleaseIntArrayElements(numBytesOfPlainDataObj, dst, 0);
         dst = NULL;
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index a52b24d..6176f0f 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -245,7 +245,7 @@
                         fields.createConfigMethod,
                         SkBitmap::kRGB_565_Config);
 
-    size_t width, height;
+    uint32_t width, height;
     bool swapWidthAndHeight = false;
     if (videoFrame->mRotationAngle == 90 || videoFrame->mRotationAngle == 270) {
         width = videoFrame->mHeight;
@@ -276,8 +276,8 @@
 
     if (videoFrame->mDisplayWidth  != videoFrame->mWidth ||
         videoFrame->mDisplayHeight != videoFrame->mHeight) {
-        size_t displayWidth = videoFrame->mDisplayWidth;
-        size_t displayHeight = videoFrame->mDisplayHeight;
+        uint32_t displayWidth = videoFrame->mDisplayWidth;
+        uint32_t displayHeight = videoFrame->mDisplayHeight;
         if (swapWidthAndHeight) {
             displayWidth = videoFrame->mDisplayHeight;
             displayHeight = videoFrame->mDisplayWidth;
diff --git a/media/jni/mediaeditor/Android.mk b/media/jni/mediaeditor/Android.mk
index 6be7fdd..5d2378d 100644
--- a/media/jni/mediaeditor/Android.mk
+++ b/media/jni/mediaeditor/Android.mk
@@ -48,7 +48,6 @@
 
 LOCAL_SHARED_LIBRARIES := \
     libandroid_runtime \
-    libaudioflinger \
     libaudioutils \
     libbinder \
     libcutils \
diff --git a/opengl/java/android/opengl/EGL14.java b/opengl/java/android/opengl/EGL14.java
index b93557d..cf09c58 100644
--- a/opengl/java/android/opengl/EGL14.java
+++ b/opengl/java/android/opengl/EGL14.java
@@ -160,6 +160,13 @@
         int display_id
     );
 
+    /**
+     * {@hide}
+     */
+    public static native EGLDisplay eglGetDisplay(
+        long display_id
+    );
+
     // C function EGLBoolean eglInitialize ( EGLDisplay dpy, EGLint *major, EGLint *minor )
 
     public static native boolean eglInitialize(
@@ -324,7 +331,7 @@
     );
 
     // C function EGLSurface eglCreatePbufferFromClientBuffer ( EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list )
-
+    // TODO Deprecate the below method
     public static native EGLSurface eglCreatePbufferFromClientBuffer(
         EGLDisplay dpy,
         int buftype,
@@ -333,6 +340,18 @@
         int[] attrib_list,
         int offset
     );
+    // TODO Unhide the below method
+    /**
+     * {@hide}
+     */
+    public static native EGLSurface eglCreatePbufferFromClientBuffer(
+        EGLDisplay dpy,
+        int buftype,
+        long buffer,
+        EGLConfig config,
+        int[] attrib_list,
+        int offset
+    );
 
     // C function EGLBoolean eglSurfaceAttrib ( EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value )
 
diff --git a/opengl/java/android/opengl/EGLConfig.java b/opengl/java/android/opengl/EGLConfig.java
index a7a6bbb..9881070 100644
--- a/opengl/java/android/opengl/EGLConfig.java
+++ b/opengl/java/android/opengl/EGLConfig.java
@@ -22,7 +22,7 @@
  *
  */
 public class EGLConfig extends EGLObjectHandle {
-    private EGLConfig(int handle) {
+    private EGLConfig(long handle) {
         super(handle);
     }
 
@@ -32,6 +32,6 @@
         if (!(o instanceof EGLConfig)) return false;
 
         EGLConfig that = (EGLConfig) o;
-        return getHandle() == that.getHandle();
+        return getNativeHandle() == that.getNativeHandle();
     }
 }
diff --git a/opengl/java/android/opengl/EGLContext.java b/opengl/java/android/opengl/EGLContext.java
index c93bd6e..f791e7e 100644
--- a/opengl/java/android/opengl/EGLContext.java
+++ b/opengl/java/android/opengl/EGLContext.java
@@ -22,7 +22,7 @@
  *
  */
 public class EGLContext extends EGLObjectHandle {
-    private EGLContext(int handle) {
+    private EGLContext(long handle) {
         super(handle);
     }
 
@@ -32,6 +32,6 @@
         if (!(o instanceof EGLContext)) return false;
 
         EGLContext that = (EGLContext) o;
-        return getHandle() == that.getHandle();
+        return getNativeHandle() == that.getNativeHandle();
     }
 }
diff --git a/opengl/java/android/opengl/EGLDisplay.java b/opengl/java/android/opengl/EGLDisplay.java
index 5b8043a..e872761 100644
--- a/opengl/java/android/opengl/EGLDisplay.java
+++ b/opengl/java/android/opengl/EGLDisplay.java
@@ -22,7 +22,7 @@
  *
  */
 public class EGLDisplay extends EGLObjectHandle {
-    private EGLDisplay(int handle) {
+    private EGLDisplay(long handle) {
         super(handle);
     }
 
@@ -32,6 +32,6 @@
         if (!(o instanceof EGLDisplay)) return false;
 
         EGLDisplay that = (EGLDisplay) o;
-        return getHandle() == that.getHandle();
+        return getNativeHandle() == that.getNativeHandle();
     }
 }
diff --git a/opengl/java/android/opengl/EGLObjectHandle.java b/opengl/java/android/opengl/EGLObjectHandle.java
index d2710de..e6e3976 100644
--- a/opengl/java/android/opengl/EGLObjectHandle.java
+++ b/opengl/java/android/opengl/EGLObjectHandle.java
@@ -22,12 +22,20 @@
  *
  */
 public abstract class EGLObjectHandle {
-    private final int mHandle;
+    private final long mHandle;
 
+    // TODO Deprecate EGLObjectHandle(int) method
     protected EGLObjectHandle(int handle) {
         mHandle = handle;
     }
-
+    // TODO Unhide the EGLObjectHandle(long) method
+    /**
+     * {@hide}
+     */
+    protected EGLObjectHandle(long handle) {
+        mHandle = handle;
+    }
+    // TODO Deprecate getHandle() method in favor of getNativeHandle()
     /**
      * Returns the native handle of the wrapped EGL object. This handle can be
      * cast to the corresponding native type on the native side.
@@ -37,11 +45,27 @@
      * @return the native handle of the wrapped EGL object.
      */
     public int getHandle() {
-        return mHandle;
+        if ((mHandle & 0xffffffffL) != mHandle) {
+            throw new UnsupportedOperationException();
+        }
+        return (int)mHandle;
     }
 
+    // TODO Unhide getNativeHandle() method
+    /**
+     * {@hide}
+     */
+    public long getNativeHandle() {
+        return mHandle;
+    }
     @Override
     public int hashCode() {
-        return getHandle();
+        /*
+         * Based on the algorithm suggested in
+         * http://developer.android.com/reference/java/lang/Object.html
+         */
+        int result = 17;
+        result = 31 * result + (int) (mHandle ^ (mHandle >>> 32));
+        return result;
     }
 }
diff --git a/opengl/java/android/opengl/EGLSurface.java b/opengl/java/android/opengl/EGLSurface.java
index c379dc9..c200f72 100644
--- a/opengl/java/android/opengl/EGLSurface.java
+++ b/opengl/java/android/opengl/EGLSurface.java
@@ -22,7 +22,7 @@
  *
  */
 public class EGLSurface extends EGLObjectHandle {
-    private EGLSurface(int handle) {
+    private EGLSurface(long handle) {
         super(handle);
     }
 
@@ -32,6 +32,6 @@
         if (!(o instanceof EGLSurface)) return false;
 
         EGLSurface that = (EGLSurface) o;
-        return getHandle() == that.getHandle();
+        return getNativeHandle() == that.getNativeHandle();
     }
 }
diff --git a/packages/services/PacProcessor/jni/Android.mk b/packages/services/PacProcessor/jni/Android.mk
index f16c90b..8a60927 100644
--- a/packages/services/PacProcessor/jni/Android.mk
+++ b/packages/services/PacProcessor/jni/Android.mk
@@ -35,6 +35,7 @@
 
 LOCAL_MODULE := libjni_pacprocessor
 LOCAL_MODULE_TAGS := optional
+LOCAL_32_BIT_ONLY := true
 
 include external/stlport/libstlport.mk
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index c33bd35..aeaa18f 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -3984,7 +3984,7 @@
                                 telephonyService.silenceRinger();
                             } else if ((mIncallPowerBehavior
                                     & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
-                                    && telephonyService.isOffhook()) {
+                                    && telephonyService.isOffhook() && isScreenOn) {
                                 // Otherwise, if "Power button ends call" is enabled,
                                 // the Power button will hang up any current active call.
                                 hungUp = telephonyService.endCall();
diff --git a/rs/java/android/renderscript/AllocationAdapter.java b/rs/java/android/renderscript/AllocationAdapter.java
index b77d087..fd20cae 100644
--- a/rs/java/android/renderscript/AllocationAdapter.java
+++ b/rs/java/android/renderscript/AllocationAdapter.java
@@ -224,7 +224,6 @@
     }
 
     static public AllocationAdapter create2D(RenderScript rs, Allocation a) {
-        android.util.Log.e("rs", "create2d " + a);
         rs.validate();
         AllocationAdapter aa = new AllocationAdapter(0, rs, a);
         aa.mConstrainedLOD = true;
diff --git a/rs/java/android/renderscript/BaseObj.java b/rs/java/android/renderscript/BaseObj.java
index 842aa23..1372ab7 100644
--- a/rs/java/android/renderscript/BaseObj.java
+++ b/rs/java/android/renderscript/BaseObj.java
@@ -122,7 +122,8 @@
             // must include nObjDestroy in the critical section
             ReentrantReadWriteLock.ReadLock rlock = mRS.mRWLock.readLock();
             rlock.lock();
-            if(mRS.isAlive()) {
+            // AllocationAdapters are BaseObjs with an ID of 0 but should not be passed to nObjDestroy
+            if(mRS.isAlive() && mID != 0) {
                 mRS.nObjDestroy(mID);
             }
             rlock.unlock();
@@ -180,6 +181,10 @@
         if (this == obj)
             return true;
 
+        if (obj == null) {
+            return false;
+        }
+
         if (getClass() != obj.getClass()) {
             return false;
         }
diff --git a/rs/java/android/renderscript/Element.java b/rs/java/android/renderscript/Element.java
index 2932770..aa5d687 100644
--- a/rs/java/android/renderscript/Element.java
+++ b/rs/java/android/renderscript/Element.java
@@ -803,8 +803,6 @@
     void updateFromNative() {
         super.updateFromNative();
 
-        // FIXME: updateFromNative is broken in JNI for 64-bit
-
         // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements
         int[] dataBuffer = new int[5];
         mRS.nElementGetNativeData(getID(mRS), dataBuffer);
@@ -831,7 +829,7 @@
             mArraySizes = new int[numSubElements];
             mOffsetInBytes = new int[numSubElements];
 
-            int[] subElementIds = new int[numSubElements];
+            long[] subElementIds = new long[numSubElements];
             mRS.nElementGetSubElements(getID(mRS), subElementIds, mElementNames, mArraySizes);
             for(int i = 0; i < numSubElements; i ++) {
                 mElements[i] = new Element(subElementIds[i], mRS);
@@ -1090,10 +1088,9 @@
             java.lang.System.arraycopy(mElementNames, 0, sin, 0, mCount);
             java.lang.System.arraycopy(mArraySizes, 0, asin, 0, mCount);
 
-            // FIXME: broken for 64-bit
-            int[] ids = new int[ein.length];
+            long[] ids = new long[ein.length];
             for (int ct = 0; ct < ein.length; ct++ ) {
-                ids[ct] = (int)ein[ct].getID(mRS);
+                ids[ct] = ein[ct].getID(mRS);
             }
             long id = mRS.nElementCreate2(ids, sin, asin);
             return new Element(id, mRS, ein, sin, asin);
diff --git a/rs/java/android/renderscript/Mesh.java b/rs/java/android/renderscript/Mesh.java
index 9ce3fb2..ca0da9d 100644
--- a/rs/java/android/renderscript/Mesh.java
+++ b/rs/java/android/renderscript/Mesh.java
@@ -154,8 +154,8 @@
         int vtxCount = mRS.nMeshGetVertexBufferCount(getID(mRS));
         int idxCount = mRS.nMeshGetIndexCount(getID(mRS));
 
-        int[] vtxIDs = new int[vtxCount];
-        int[] idxIDs = new int[idxCount];
+        long[] vtxIDs = new long[vtxCount];
+        long[] idxIDs = new long[idxCount];
         int[] primitives = new int[idxCount];
 
         mRS.nMeshGetVertices(getID(mRS), vtxIDs, vtxCount);
@@ -350,8 +350,8 @@
         **/
         public Mesh create() {
             mRS.validate();
-            int[] vtx = new int[mVertexTypeCount];
-            int[] idx = new int[mIndexTypes.size()];
+            long[] vtx = new long[mVertexTypeCount];
+            long[] idx = new long[mIndexTypes.size()];
             int[] prim = new int[mIndexTypes.size()];
 
             Allocation[] vertexBuffers = new Allocation[mVertexTypeCount];
@@ -367,7 +367,7 @@
                     alloc = Allocation.createSized(mRS, entry.e, entry.size, mUsage);
                 }
                 vertexBuffers[ct] = alloc;
-                vtx[ct] = (int)alloc.getID(mRS);
+                vtx[ct] = alloc.getID(mRS);
             }
 
             for(int ct = 0; ct < mIndexTypes.size(); ct ++) {
@@ -382,7 +382,7 @@
                 indexBuffers[ct] = alloc;
                 primitives[ct] = entry.prim;
 
-                idx[ct] = (int)allocID;
+                idx[ct] = allocID;
                 prim[ct] = entry.prim.mID;
             }
 
@@ -506,8 +506,8 @@
         public Mesh create() {
             mRS.validate();
 
-            int[] vtx = new int[mVertexTypeCount];
-            int[] idx = new int[mIndexTypes.size()];
+            long[] vtx = new long[mVertexTypeCount];
+            long[] idx = new long[mIndexTypes.size()];
             int[] prim = new int[mIndexTypes.size()];
 
             Allocation[] indexBuffers = new Allocation[mIndexTypes.size()];
@@ -517,7 +517,7 @@
             for(int ct = 0; ct < mVertexTypeCount; ct ++) {
                 Entry entry = mVertexTypes[ct];
                 vertexBuffers[ct] = entry.a;
-                vtx[ct] = (int)entry.a.getID(mRS);
+                vtx[ct] = entry.a.getID(mRS);
             }
 
             for(int ct = 0; ct < mIndexTypes.size(); ct ++) {
@@ -526,7 +526,7 @@
                 indexBuffers[ct] = entry.a;
                 primitives[ct] = entry.prim;
 
-                idx[ct] = (int)allocID;
+                idx[ct] = allocID;
                 prim[ct] = entry.prim.mID;
             }
 
diff --git a/rs/java/android/renderscript/ProgramFragment.java b/rs/java/android/renderscript/ProgramFragment.java
index 5e886a3..4bb527b 100644
--- a/rs/java/android/renderscript/ProgramFragment.java
+++ b/rs/java/android/renderscript/ProgramFragment.java
@@ -65,25 +65,25 @@
          */
         public ProgramFragment create() {
             mRS.validate();
-            int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
+            long[] tmp = new long[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
             String[] texNames = new String[mTextureCount];
             int idx = 0;
 
             for (int i=0; i < mInputCount; i++) {
                 tmp[idx++] = ProgramParam.INPUT.mID;
-                tmp[idx++] = (int)mInputs[i].getID(mRS);
+                tmp[idx++] = mInputs[i].getID(mRS);
             }
             for (int i=0; i < mOutputCount; i++) {
                 tmp[idx++] = ProgramParam.OUTPUT.mID;
-                tmp[idx++] = (int)mOutputs[i].getID(mRS);
+                tmp[idx++] = mOutputs[i].getID(mRS);
             }
             for (int i=0; i < mConstantCount; i++) {
                 tmp[idx++] = ProgramParam.CONSTANT.mID;
-                tmp[idx++] = (int)mConstants[i].getID(mRS);
+                tmp[idx++] = mConstants[i].getID(mRS);
             }
             for (int i=0; i < mTextureCount; i++) {
                 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
-                tmp[idx++] = (int)mTextureTypes[i].mID;
+                tmp[idx++] = mTextureTypes[i].mID;
                 texNames[i] = mTextureNames[i];
             }
 
diff --git a/rs/java/android/renderscript/ProgramFragmentFixedFunction.java b/rs/java/android/renderscript/ProgramFragmentFixedFunction.java
index 22aed0a..2fe68be 100644
--- a/rs/java/android/renderscript/ProgramFragmentFixedFunction.java
+++ b/rs/java/android/renderscript/ProgramFragmentFixedFunction.java
@@ -52,25 +52,25 @@
          */
         public ProgramFragmentFixedFunction create() {
             mRS.validate();
-            int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
+            long[] tmp = new long[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
             String[] texNames = new String[mTextureCount];
             int idx = 0;
 
             for (int i=0; i < mInputCount; i++) {
                 tmp[idx++] = ProgramParam.INPUT.mID;
-                tmp[idx++] = (int)mInputs[i].getID(mRS);
+                tmp[idx++] = mInputs[i].getID(mRS);
             }
             for (int i=0; i < mOutputCount; i++) {
                 tmp[idx++] = ProgramParam.OUTPUT.mID;
-                tmp[idx++] = (int)mOutputs[i].getID(mRS);
+                tmp[idx++] = mOutputs[i].getID(mRS);
             }
             for (int i=0; i < mConstantCount; i++) {
                 tmp[idx++] = ProgramParam.CONSTANT.mID;
-                tmp[idx++] = (int)mConstants[i].getID(mRS);
+                tmp[idx++] = mConstants[i].getID(mRS);
             }
             for (int i=0; i < mTextureCount; i++) {
                 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
-                tmp[idx++] = (int)mTextureTypes[i].mID;
+                tmp[idx++] = mTextureTypes[i].mID;
                 texNames[i] = mTextureNames[i];
             }
 
diff --git a/rs/java/android/renderscript/ProgramVertex.java b/rs/java/android/renderscript/ProgramVertex.java
index b6886e1..d3a51de 100644
--- a/rs/java/android/renderscript/ProgramVertex.java
+++ b/rs/java/android/renderscript/ProgramVertex.java
@@ -126,25 +126,25 @@
          */
         public ProgramVertex create() {
             mRS.validate();
-            int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
+            long[] tmp = new long[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
             String[] texNames = new String[mTextureCount];
             int idx = 0;
 
             for (int i=0; i < mInputCount; i++) {
                 tmp[idx++] = ProgramParam.INPUT.mID;
-                tmp[idx++] = (int)mInputs[i].getID(mRS);
+                tmp[idx++] = mInputs[i].getID(mRS);
             }
             for (int i=0; i < mOutputCount; i++) {
                 tmp[idx++] = ProgramParam.OUTPUT.mID;
-                tmp[idx++] = (int)mOutputs[i].getID(mRS);
+                tmp[idx++] = mOutputs[i].getID(mRS);
             }
             for (int i=0; i < mConstantCount; i++) {
                 tmp[idx++] = ProgramParam.CONSTANT.mID;
-                tmp[idx++] = (int)mConstants[i].getID(mRS);
+                tmp[idx++] = mConstants[i].getID(mRS);
             }
             for (int i=0; i < mTextureCount; i++) {
                 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
-                tmp[idx++] = (int)mTextureTypes[i].mID;
+                tmp[idx++] = mTextureTypes[i].mID;
                 texNames[i] = mTextureNames[i];
             }
 
diff --git a/rs/java/android/renderscript/ProgramVertexFixedFunction.java b/rs/java/android/renderscript/ProgramVertexFixedFunction.java
index c479c77..a350154 100644
--- a/rs/java/android/renderscript/ProgramVertexFixedFunction.java
+++ b/rs/java/android/renderscript/ProgramVertexFixedFunction.java
@@ -79,25 +79,25 @@
          */
         public ProgramVertexFixedFunction create() {
             mRS.validate();
-            int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
+            long[] tmp = new long[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
             String[] texNames = new String[mTextureCount];
             int idx = 0;
 
             for (int i=0; i < mInputCount; i++) {
                 tmp[idx++] = ProgramParam.INPUT.mID;
-                tmp[idx++] = (int)mInputs[i].getID(mRS);
+                tmp[idx++] = mInputs[i].getID(mRS);
             }
             for (int i=0; i < mOutputCount; i++) {
                 tmp[idx++] = ProgramParam.OUTPUT.mID;
-                tmp[idx++] = (int)mOutputs[i].getID(mRS);
+                tmp[idx++] = mOutputs[i].getID(mRS);
             }
             for (int i=0; i < mConstantCount; i++) {
                 tmp[idx++] = ProgramParam.CONSTANT.mID;
-                tmp[idx++] = (int)mConstants[i].getID(mRS);
+                tmp[idx++] = mConstants[i].getID(mRS);
             }
             for (int i=0; i < mTextureCount; i++) {
                 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
-                tmp[idx++] = (int)mTextureTypes[i].mID;
+                tmp[idx++] = mTextureTypes[i].mID;
                 texNames[i] = mTextureNames[i];
             }
 
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 8618764..ea25f58 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -103,6 +103,20 @@
 
     static File mCacheDir;
 
+    // this should be a monotonically increasing ID
+    // used in conjunction with the API version of a device
+    static final long sMinorID = 1;
+
+    /**
+     * Returns an identifier that can be used to identify a particular
+     * minor version of RS.
+     *
+     * @hide
+     */
+    public static long getMinorID() {
+        return sMinorID;
+    }
+
      /**
      * Sets the directory to use as a persistent storage for the
      * renderscript object file cache.
@@ -225,8 +239,8 @@
         rsnContextSendMessage(mContext, id, data);
     }
 
-    native void rsnContextBindRootScript(long con, int script);
-    synchronized void nContextBindRootScript(int script) {
+    native void rsnContextBindRootScript(long con, long script);
+    synchronized void nContextBindRootScript(long script) {
         validate();
         rsnContextBindRootScript(mContext, script);
     }
@@ -235,23 +249,23 @@
         validate();
         rsnContextBindSampler(mContext, sampler, slot);
     }
-    native void rsnContextBindProgramStore(long con, int pfs);
-    synchronized void nContextBindProgramStore(int pfs) {
+    native void rsnContextBindProgramStore(long con, long pfs);
+    synchronized void nContextBindProgramStore(long pfs) {
         validate();
         rsnContextBindProgramStore(mContext, pfs);
     }
-    native void rsnContextBindProgramFragment(long con, int pf);
-    synchronized void nContextBindProgramFragment(int pf) {
+    native void rsnContextBindProgramFragment(long con, long pf);
+    synchronized void nContextBindProgramFragment(long pf) {
         validate();
         rsnContextBindProgramFragment(mContext, pf);
     }
-    native void rsnContextBindProgramVertex(long con, int pv);
-    synchronized void nContextBindProgramVertex(int pv) {
+    native void rsnContextBindProgramVertex(long con, long pv);
+    synchronized void nContextBindProgramVertex(long pv) {
         validate();
         rsnContextBindProgramVertex(mContext, pv);
     }
-    native void rsnContextBindProgramRaster(long con, int pr);
-    synchronized void nContextBindProgramRaster(int pr) {
+    native void rsnContextBindProgramRaster(long con, long pr);
+    synchronized void nContextBindProgramRaster(long pr) {
         validate();
         rsnContextBindProgramRaster(mContext, pr);
     }
@@ -293,8 +307,8 @@
         validate();
         return rsnElementCreate(mContext, type, kind, norm, vecSize);
     }
-    native long rsnElementCreate2(long con, int[]elements, String[] names, int[] arraySizes);
-    synchronized long nElementCreate2(int[] elements, String[] names, int[] arraySizes) {
+    native long rsnElementCreate2(long con, long[] elements, String[] names, int[] arraySizes);
+    synchronized long nElementCreate2(long[] elements, String[] names, int[] arraySizes) {
         validate();
         return rsnElementCreate2(mContext, elements, names, arraySizes);
     }
@@ -304,8 +318,8 @@
         rsnElementGetNativeData(mContext, id, elementData);
     }
     native void rsnElementGetSubElements(long con, long id,
-                                         int[] IDs, String[] names, int[] arraySizes);
-    synchronized void nElementGetSubElements(long id, int[] IDs, String[] names, int[] arraySizes) {
+                                         long[] IDs, String[] names, int[] arraySizes);
+    synchronized void nElementGetSubElements(long id, long[] IDs, String[] names, int[] arraySizes) {
         validate();
         rsnElementGetSubElements(mContext, id, IDs, names, arraySizes);
     }
@@ -315,14 +329,14 @@
         validate();
         return rsnTypeCreate(mContext, eid, x, y, z, mips, faces, yuv);
     }
-    native void rsnTypeGetNativeData(long con, long id, int[] typeData);
-    synchronized void nTypeGetNativeData(long id, int[] typeData) {
+    native void rsnTypeGetNativeData(long con, long id, long[] typeData);
+    synchronized void nTypeGetNativeData(long id, long[] typeData) {
         validate();
         rsnTypeGetNativeData(mContext, id, typeData);
     }
 
-    native long rsnAllocationCreateTyped(long con, long type, int mip, int usage, int pointer);
-    synchronized long nAllocationCreateTyped(long type, int mip, int usage, int pointer) {
+    native long rsnAllocationCreateTyped(long con, long type, int mip, int usage, long pointer);
+    synchronized long nAllocationCreateTyped(long type, int mip, int usage, long pointer) {
         validate();
         return rsnAllocationCreateTyped(mContext, type, mip, usage, pointer);
     }
@@ -690,8 +704,8 @@
         return rsnScriptFieldIDCreate(mContext, sid, slot);
     }
 
-    native long rsnScriptGroupCreate(long con, int[] kernels, int[] src, int[] dstk, int[] dstf, int[] types);
-    synchronized long nScriptGroupCreate(int[] kernels, int[] src, int[] dstk, int[] dstf, int[] types) {
+    native long rsnScriptGroupCreate(long con, long[] kernels, long[] src, long[] dstk, long[] dstf, long[] types);
+    synchronized long nScriptGroupCreate(long[] kernels, long[] src, long[] dstk, long[] dstf, long[] types) {
         validate();
         return rsnScriptGroupCreate(mContext, kernels, src, dstk, dstf, types);
     }
@@ -754,19 +768,19 @@
         validate();
         rsnProgramBindSampler(mContext, vpf, slot, s);
     }
-    native long rsnProgramFragmentCreate(long con, String shader, String[] texNames, int[] params);
-    synchronized long nProgramFragmentCreate(String shader, String[] texNames, int[] params) {
+    native long rsnProgramFragmentCreate(long con, String shader, String[] texNames, long[] params);
+    synchronized long nProgramFragmentCreate(String shader, String[] texNames, long[] params) {
         validate();
         return rsnProgramFragmentCreate(mContext, shader, texNames, params);
     }
-    native long rsnProgramVertexCreate(long con, String shader, String[] texNames, int[] params);
-    synchronized long nProgramVertexCreate(String shader, String[] texNames, int[] params) {
+    native long rsnProgramVertexCreate(long con, String shader, String[] texNames, long[] params);
+    synchronized long nProgramVertexCreate(String shader, String[] texNames, long[] params) {
         validate();
         return rsnProgramVertexCreate(mContext, shader, texNames, params);
     }
 
-    native long rsnMeshCreate(long con, int[] vtx, int[] idx, int[] prim);
-    synchronized long nMeshCreate(int[] vtx, int[] idx, int[] prim) {
+    native long rsnMeshCreate(long con, long[] vtx, long[] idx, int[] prim);
+    synchronized long nMeshCreate(long[] vtx, long[] idx, int[] prim) {
         validate();
         return rsnMeshCreate(mContext, vtx, idx, prim);
     }
@@ -780,13 +794,13 @@
         validate();
         return rsnMeshGetIndexCount(mContext, id);
     }
-    native void rsnMeshGetVertices(long con, long id, int[] vtxIds, int vtxIdCount);
-    synchronized void nMeshGetVertices(long id, int[] vtxIds, int vtxIdCount) {
+    native void rsnMeshGetVertices(long con, long id, long[] vtxIds, int vtxIdCount);
+    synchronized void nMeshGetVertices(long id, long[] vtxIds, int vtxIdCount) {
         validate();
         rsnMeshGetVertices(mContext, id, vtxIds, vtxIdCount);
     }
-    native void rsnMeshGetIndices(long con, long id, int[] idxIds, int[] primitives, int vtxIdCount);
-    synchronized void nMeshGetIndices(long id, int[] idxIds, int[] primitives, int vtxIdCount) {
+    native void rsnMeshGetIndices(long con, long id, long[] idxIds, int[] primitives, int vtxIdCount);
+    synchronized void nMeshGetIndices(long id, long[] idxIds, int[] primitives, int vtxIdCount) {
         validate();
         rsnMeshGetIndices(mContext, id, idxIds, primitives, vtxIdCount);
     }
@@ -990,6 +1004,14 @@
         }
     }
 
+    void validateObject(BaseObj o) {
+        if (o != null) {
+            if (o.mRS != this) {
+                throw new RSIllegalArgumentException("Attempting to use an object across contexts.");
+            }
+        }
+    }
+
     void validate() {
         if (mContext == 0) {
             throw new RSInvalidStateException("Calling RS with no Context active.");
diff --git a/rs/java/android/renderscript/Script.java b/rs/java/android/renderscript/Script.java
index a1f2287..0e46f94 100644
--- a/rs/java/android/renderscript/Script.java
+++ b/rs/java/android/renderscript/Script.java
@@ -128,6 +128,9 @@
      *
      */
     protected void forEach(int slot, Allocation ain, Allocation aout, FieldPacker v) {
+        mRS.validate();
+        mRS.validateObject(ain);
+        mRS.validateObject(aout);
         if (ain == null && aout == null) {
             throw new RSIllegalArgumentException(
                 "At least one of ain or aout is required to be non-null.");
@@ -152,6 +155,9 @@
      *
      */
     protected void forEach(int slot, Allocation ain, Allocation aout, FieldPacker v, LaunchOptions sc) {
+        mRS.validate();
+        mRS.validateObject(ain);
+        mRS.validateObject(aout);
         if (ain == null && aout == null) {
             throw new RSIllegalArgumentException(
                 "At least one of ain or aout is required to be non-null.");
@@ -187,6 +193,7 @@
      */
     public void bindAllocation(Allocation va, int slot) {
         mRS.validate();
+        mRS.validateObject(va);
         if (va != null) {
             if (mRS.getApplicationContext().getApplicationInfo().targetSdkVersion >= 20) {
                 final Type t = va.mType;
@@ -263,6 +270,8 @@
      *
      */
     public void setVar(int index, BaseObj o) {
+        mRS.validate();
+        mRS.validateObject(o);
         mRS.nScriptSetVarObj(getID(mRS), index, (o == null) ? 0 : o.getID(mRS));
     }
 
diff --git a/rs/java/android/renderscript/ScriptGroup.java b/rs/java/android/renderscript/ScriptGroup.java
index 48dba30..1200a66 100644
--- a/rs/java/android/renderscript/ScriptGroup.java
+++ b/rs/java/android/renderscript/ScriptGroup.java
@@ -380,7 +380,6 @@
          * @return ScriptGroup The new ScriptGroup
          */
         public ScriptGroup create() {
-            // FIXME: this is broken for 64-bit
 
             if (mNodes.size() == 0) {
                 throw new RSInvalidStateException("Empty script groups are not allowed");
@@ -395,13 +394,13 @@
             ArrayList<IO> inputs = new ArrayList<IO>();
             ArrayList<IO> outputs = new ArrayList<IO>();
 
-            int[] kernels = new int[mKernelCount];
+            long[] kernels = new long[mKernelCount];
             int idx = 0;
             for (int ct=0; ct < mNodes.size(); ct++) {
                 Node n = mNodes.get(ct);
                 for (int ct2=0; ct2 < n.mKernels.size(); ct2++) {
                     final Script.KernelID kid = n.mKernels.get(ct2);
-                    kernels[idx++] = (int)kid.getID(mRS);
+                    kernels[idx++] = kid.getID(mRS);
 
                     boolean hasInput = false;
                     boolean hasOutput = false;
@@ -428,21 +427,21 @@
                 throw new RSRuntimeException("Count mismatch, should not happen.");
             }
 
-            int[] src = new int[mLines.size()];
-            int[] dstk = new int[mLines.size()];
-            int[] dstf = new int[mLines.size()];
-            int[] types = new int[mLines.size()];
+            long[] src = new long[mLines.size()];
+            long[] dstk = new long[mLines.size()];
+            long[] dstf = new long[mLines.size()];
+            long[] types = new long[mLines.size()];
 
             for (int ct=0; ct < mLines.size(); ct++) {
                 ConnectLine cl = mLines.get(ct);
-                src[ct] = (int)cl.mFrom.getID(mRS);
+                src[ct] = cl.mFrom.getID(mRS);
                 if (cl.mToK != null) {
-                    dstk[ct] = (int)cl.mToK.getID(mRS);
+                    dstk[ct] = cl.mToK.getID(mRS);
                 }
                 if (cl.mToF != null) {
-                    dstf[ct] = (int)cl.mToF.getID(mRS);
+                    dstf[ct] = cl.mToF.getID(mRS);
                 }
-                types[ct] = (int)cl.mAllocationType.getID(mRS);
+                types[ct] = cl.mAllocationType.getID(mRS);
             }
 
             long id = mRS.nScriptGroupCreate(kernels, src, dstk, dstf, types);
diff --git a/rs/java/android/renderscript/Type.java b/rs/java/android/renderscript/Type.java
index 7bdd360..ce7f571 100644
--- a/rs/java/android/renderscript/Type.java
+++ b/rs/java/android/renderscript/Type.java
@@ -196,20 +196,18 @@
 
     @Override
     void updateFromNative() {
-        // FIXME: rsaTypeGetNativeData needs 32-bit and 64-bit paths
-
-        // We have 6 integer to obtain mDimX; mDimY; mDimZ;
+        // We have 6 integer/long to obtain mDimX; mDimY; mDimZ;
         // mDimLOD; mDimFaces; mElement;
-        int[] dataBuffer = new int[6];
-        mRS.nTypeGetNativeData((int)getID(mRS), dataBuffer);
+        long[] dataBuffer = new long[6];
+        mRS.nTypeGetNativeData(getID(mRS), dataBuffer);
 
-        mDimX = dataBuffer[0];
-        mDimY = dataBuffer[1];
-        mDimZ = dataBuffer[2];
+        mDimX = (int)dataBuffer[0];
+        mDimY = (int)dataBuffer[1];
+        mDimZ = (int)dataBuffer[2];
         mDimMipmaps = dataBuffer[3] == 1 ? true : false;
         mDimFaces = dataBuffer[4] == 1 ? true : false;
 
-        int elementID = dataBuffer[5];
+        long elementID = dataBuffer[5];
         if(elementID != 0) {
             mElement = new Element(elementID, mRS);
             mElement.updateFromNative();
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 80a5da2..9b89eb9 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -412,13 +412,21 @@
 
 static jlong
 nElementCreate2(JNIEnv *_env, jobject _this, jlong con,
-                jintArray _ids, jobjectArray _names, jintArray _arraySizes)
+                jlongArray _ids, jobjectArray _names, jintArray _arraySizes)
 {
     int fieldCount = _env->GetArrayLength(_ids);
     LOG_API("nElementCreate2, con(%p)", (RsContext)con);
 
-    jint *ids = _env->GetIntArrayElements(_ids, NULL);
-    jint *arraySizes = _env->GetIntArrayElements(_arraySizes, NULL);
+    jlong *jIds = _env->GetLongArrayElements(_ids, NULL);
+    jint *jArraySizes = _env->GetIntArrayElements(_arraySizes, NULL);
+
+    RsElement *ids = (RsElement*)malloc(fieldCount * sizeof(RsElement));
+    uint32_t *arraySizes = (uint32_t *)malloc(fieldCount * sizeof(uint32_t));
+
+    for(int i = 0; i < fieldCount; i ++) {
+        ids[i] = (RsElement)jIds[i];
+        arraySizes[i] = (uint32_t)jArraySizes[i];
+    }
 
     AutoJavaStringArrayToUTF8 names(_env, _names, fieldCount);
 
@@ -426,12 +434,15 @@
     size_t *sizeArray = names.c_str_len();
 
     jlong id = (jlong)rsElementCreate2((RsContext)con,
-                                     (RsElement *)ids, fieldCount,
+                                     (const RsElement *)ids, fieldCount,
                                      nameArray, fieldCount * sizeof(size_t),  sizeArray,
                                      (const uint32_t *)arraySizes, fieldCount);
 
-    _env->ReleaseIntArrayElements(_ids, ids, JNI_ABORT);
-    _env->ReleaseIntArrayElements(_arraySizes, arraySizes, JNI_ABORT);
+    free(ids);
+    free(arraySizes);
+    _env->ReleaseLongArrayElements(_ids, jIds, JNI_ABORT);
+    _env->ReleaseIntArrayElements(_arraySizes, jArraySizes, JNI_ABORT);
+
     return (jlong)id;
 }
 
@@ -444,34 +455,37 @@
     // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements
     assert(dataSize == 5);
 
-    uint32_t elementData[5];
+    uintptr_t elementData[5];
     rsaElementGetNativeData((RsContext)con, (RsElement)id, elementData, dataSize);
 
     for(jint i = 0; i < dataSize; i ++) {
-        _env->SetIntArrayRegion(_elementData, i, 1, (const jint*)&elementData[i]);
+        const jint data = (jint)elementData[i];
+        _env->SetIntArrayRegion(_elementData, i, 1, &data);
     }
 }
 
 
 static void
 nElementGetSubElements(JNIEnv *_env, jobject _this, jlong con, jlong id,
-                       jintArray _IDs,
+                       jlongArray _IDs,
                        jobjectArray _names,
                        jintArray _arraySizes)
 {
-    int dataSize = _env->GetArrayLength(_IDs);
+    uint32_t dataSize = _env->GetArrayLength(_IDs);
     LOG_API("nElementGetSubElements, con(%p)", (RsContext)con);
 
-    uint32_t *ids = (uint32_t *)malloc((uint32_t)dataSize * sizeof(uint32_t));
-    const char **names = (const char **)malloc((uint32_t)dataSize * sizeof(const char *));
-    uint32_t *arraySizes = (uint32_t *)malloc((uint32_t)dataSize * sizeof(uint32_t));
+    uintptr_t *ids = (uintptr_t*)malloc(dataSize * sizeof(uintptr_t));
+    const char **names = (const char **)malloc(dataSize * sizeof(const char *));
+    uint32_t *arraySizes = (uint32_t *)malloc(dataSize * sizeof(uint32_t));
 
     rsaElementGetSubElements((RsContext)con, (RsElement)id, ids, names, arraySizes, (uint32_t)dataSize);
 
-    for(jint i = 0; i < dataSize; i++) {
+    for(uint32_t i = 0; i < dataSize; i++) {
+        const jlong id = (jlong)ids[i];
+        const jint arraySize = (jint)arraySizes[i];
         _env->SetObjectArrayElement(_names, i, _env->NewStringUTF(names[i]));
-        _env->SetIntArrayRegion(_IDs, i, 1, (const jint*)&ids[i]);
-        _env->SetIntArrayRegion(_arraySizes, i, 1, (const jint*)&arraySizes[i]);
+        _env->SetLongArrayRegion(_IDs, i, 1, &id);
+        _env->SetIntArrayRegion(_arraySizes, i, 1, &arraySize);
     }
 
     free(ids);
@@ -492,7 +506,7 @@
 }
 
 static void
-nTypeGetNativeData(JNIEnv *_env, jobject _this, jlong con, jlong id, jintArray _typeData)
+nTypeGetNativeData(JNIEnv *_env, jobject _this, jlong con, jlong id, jlongArray _typeData)
 {
     // We are packing 6 items: mDimX; mDimY; mDimZ;
     // mDimLOD; mDimFaces; mElement; into typeData
@@ -501,21 +515,22 @@
     assert(elementCount == 6);
     LOG_API("nTypeGetNativeData, con(%p)", (RsContext)con);
 
-    uint32_t typeData[6];
+    uintptr_t typeData[6];
     rsaTypeGetNativeData((RsContext)con, (RsType)id, typeData, 6);
 
     for(jint i = 0; i < elementCount; i ++) {
-        _env->SetIntArrayRegion(_typeData, i, 1, (const jint*)&typeData[i]);
+        const jlong data = (jlong)typeData[i];
+        _env->SetLongArrayRegion(_typeData, i, 1, &data);
     }
 }
 
 // -----------------------------------
 
 static jlong
-nAllocationCreateTyped(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mips, jint usage, jint pointer)
+nAllocationCreateTyped(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mips, jint usage, jlong pointer)
 {
     LOG_API("nAllocationCreateTyped, con(%p), type(%p), mip(%i), usage(%i), ptr(%p)", (RsContext)con, (RsElement)type, mips, usage, (void *)pointer);
-    return (jlong) rsAllocationCreateTyped((RsContext)con, (RsType)type, (RsAllocationMipmapControl)mips, (uint32_t)usage, (uint32_t)pointer);
+    return (jlong) rsAllocationCreateTyped((RsContext)con, (RsType)type, (RsAllocationMipmapControl)mips, (uint32_t)usage, (uintptr_t)pointer);
 }
 
 static void
@@ -601,7 +616,7 @@
     const void* ptr = bitmap.getPixels();
     jlong id = (jlong)rsAllocationCreateTyped((RsContext)con,
                                             (RsType)type, (RsAllocationMipmapControl)mip,
-                                            (uint32_t)usage, (size_t)ptr);
+                                            (uint32_t)usage, (uintptr_t)ptr);
     bitmap.unlockPixels();
     return id;
 }
@@ -1196,34 +1211,63 @@
 }
 
 static jlong
-nScriptGroupCreate(JNIEnv *_env, jobject _this, jlong con, jintArray _kernels, jintArray _src,
-    jintArray _dstk, jintArray _dstf, jintArray _types)
+nScriptGroupCreate(JNIEnv *_env, jobject _this, jlong con, jlongArray _kernels, jlongArray _src,
+    jlongArray _dstk, jlongArray _dstf, jlongArray _types)
 {
     LOG_API("nScriptGroupCreate, con(%p)", (RsContext)con);
 
-    jint kernelsLen = _env->GetArrayLength(_kernels) * sizeof(int);
-    jint *kernelsPtr = _env->GetIntArrayElements(_kernels, NULL);
-    jint srcLen = _env->GetArrayLength(_src) * sizeof(int);
-    jint *srcPtr = _env->GetIntArrayElements(_src, NULL);
-    jint dstkLen = _env->GetArrayLength(_dstk) * sizeof(int);
-    jint *dstkPtr = _env->GetIntArrayElements(_dstk, NULL);
-    jint dstfLen = _env->GetArrayLength(_dstf) * sizeof(int);
-    jint *dstfPtr = _env->GetIntArrayElements(_dstf, NULL);
-    jint typesLen = _env->GetArrayLength(_types) * sizeof(int);
-    jint *typesPtr = _env->GetIntArrayElements(_types, NULL);
+    jint kernelsLen = _env->GetArrayLength(_kernels);
+    jlong *jKernelsPtr = _env->GetLongArrayElements(_kernels, NULL);
+    RsScriptKernelID* kernelsPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * kernelsLen);
+    for(int i = 0; i < kernelsLen; ++i) {
+        kernelsPtr[i] = (RsScriptKernelID)jKernelsPtr[i];
+    }
 
-    int id = (int)rsScriptGroupCreate((RsContext)con,
-                               (RsScriptKernelID *)kernelsPtr, kernelsLen,
-                               (RsScriptKernelID *)srcPtr, srcLen,
-                               (RsScriptKernelID *)dstkPtr, dstkLen,
-                               (RsScriptFieldID *)dstfPtr, dstfLen,
-                               (RsType *)typesPtr, typesLen);
+    jint srcLen = _env->GetArrayLength(_src);
+    jlong *jSrcPtr = _env->GetLongArrayElements(_src, NULL);
+    RsScriptKernelID* srcPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * srcLen);
+    for(int i = 0; i < srcLen; ++i) {
+        srcPtr[i] = (RsScriptKernelID)jSrcPtr[i];
+    }
 
-    _env->ReleaseIntArrayElements(_kernels, kernelsPtr, 0);
-    _env->ReleaseIntArrayElements(_src, srcPtr, 0);
-    _env->ReleaseIntArrayElements(_dstk, dstkPtr, 0);
-    _env->ReleaseIntArrayElements(_dstf, dstfPtr, 0);
-    _env->ReleaseIntArrayElements(_types, typesPtr, 0);
+    jint dstkLen = _env->GetArrayLength(_dstk);
+    jlong *jDstkPtr = _env->GetLongArrayElements(_dstk, NULL);
+    RsScriptKernelID* dstkPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * dstkLen);
+    for(int i = 0; i < dstkLen; ++i) {
+        dstkPtr[i] = (RsScriptKernelID)jDstkPtr[i];
+    }
+
+    jint dstfLen = _env->GetArrayLength(_dstf);
+    jlong *jDstfPtr = _env->GetLongArrayElements(_dstf, NULL);
+    RsScriptKernelID* dstfPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * dstfLen);
+    for(int i = 0; i < dstfLen; ++i) {
+        dstfPtr[i] = (RsScriptKernelID)jDstfPtr[i];
+    }
+
+    jint typesLen = _env->GetArrayLength(_types);
+    jlong *jTypesPtr = _env->GetLongArrayElements(_types, NULL);
+    RsType* typesPtr = (RsType*) malloc(sizeof(RsType) * typesLen);
+    for(int i = 0; i < typesLen; ++i) {
+        typesPtr[i] = (RsType)jTypesPtr[i];
+    }
+
+    jlong id = (jlong)rsScriptGroupCreate((RsContext)con,
+                               (RsScriptKernelID *)kernelsPtr, kernelsLen * sizeof(RsScriptKernelID),
+                               (RsScriptKernelID *)srcPtr, srcLen * sizeof(RsScriptKernelID),
+                               (RsScriptKernelID *)dstkPtr, dstkLen * sizeof(RsScriptKernelID),
+                               (RsScriptFieldID *)dstfPtr, dstfLen * sizeof(RsScriptKernelID),
+                               (RsType *)typesPtr, typesLen * sizeof(RsType));
+
+    free(kernelsPtr);
+    free(srcPtr);
+    free(dstkPtr);
+    free(dstfPtr);
+    free(typesPtr);
+    _env->ReleaseLongArrayElements(_kernels, jKernelsPtr, 0);
+    _env->ReleaseLongArrayElements(_src, jSrcPtr, 0);
+    _env->ReleaseLongArrayElements(_dstk, jDstkPtr, 0);
+    _env->ReleaseLongArrayElements(_dstf, jDstfPtr, 0);
+    _env->ReleaseLongArrayElements(_types, jTypesPtr, 0);
     return id;
 }
 
@@ -1292,10 +1336,10 @@
 
 static jlong
 nProgramFragmentCreate(JNIEnv *_env, jobject _this, jlong con, jstring shader,
-                       jobjectArray texNames, jintArray params)
+                       jobjectArray texNames, jlongArray params)
 {
     AutoJavaStringToUTF8 shaderUTF(_env, shader);
-    jint *paramPtr = _env->GetIntArrayElements(params, NULL);
+    jlong *jParamPtr = _env->GetLongArrayElements(params, NULL);
     jint paramLen = _env->GetArrayLength(params);
 
     int texCount = _env->GetArrayLength(texNames);
@@ -1305,11 +1349,16 @@
 
     LOG_API("nProgramFragmentCreate, con(%p), paramLen(%i)", (RsContext)con, paramLen);
 
+    uintptr_t * paramPtr = (uintptr_t*) malloc(sizeof(uintptr_t) * paramLen);
+    for(int i = 0; i < paramLen; ++i) {
+        paramPtr[i] = (uintptr_t)jParamPtr[i];
+    }
     jlong ret = (jlong)rsProgramFragmentCreate((RsContext)con, shaderUTF.c_str(), shaderUTF.length(),
                                              nameArray, texCount, sizeArray,
-                                             (uint32_t *)paramPtr, paramLen);
+                                             paramPtr, paramLen);
 
-    _env->ReleaseIntArrayElements(params, paramPtr, JNI_ABORT);
+    free(paramPtr);
+    _env->ReleaseLongArrayElements(params, jParamPtr, JNI_ABORT);
     return ret;
 }
 
@@ -1318,10 +1367,10 @@
 
 static jlong
 nProgramVertexCreate(JNIEnv *_env, jobject _this, jlong con, jstring shader,
-                     jobjectArray texNames, jintArray params)
+                     jobjectArray texNames, jlongArray params)
 {
     AutoJavaStringToUTF8 shaderUTF(_env, shader);
-    jint *paramPtr = _env->GetIntArrayElements(params, NULL);
+    jlong *jParamPtr = _env->GetLongArrayElements(params, NULL);
     jint paramLen = _env->GetArrayLength(params);
 
     LOG_API("nProgramVertexCreate, con(%p), paramLen(%i)", (RsContext)con, paramLen);
@@ -1331,11 +1380,17 @@
     const char ** nameArray = names.c_str();
     size_t* sizeArray = names.c_str_len();
 
+    uintptr_t * paramPtr = (uintptr_t*) malloc(sizeof(uintptr_t) * paramLen);
+    for(int i = 0; i < paramLen; ++i) {
+        paramPtr[i] = (uintptr_t)jParamPtr[i];
+    }
+
     jlong ret = (jlong)rsProgramVertexCreate((RsContext)con, shaderUTF.c_str(), shaderUTF.length(),
                                            nameArray, texCount, sizeArray,
-                                           (uint32_t *)paramPtr, paramLen);
+                                           paramPtr, paramLen);
 
-    _env->ReleaseIntArrayElements(params, paramPtr, JNI_ABORT);
+    free(paramPtr);
+    _env->ReleaseLongArrayElements(params, jParamPtr, JNI_ABORT);
     return ret;
 }
 
@@ -1352,35 +1407,35 @@
 // ---------------------------------------------------------------------------
 
 static void
-nContextBindRootScript(JNIEnv *_env, jobject _this, jlong con, jint script)
+nContextBindRootScript(JNIEnv *_env, jobject _this, jlong con, jlong script)
 {
     LOG_API("nContextBindRootScript, con(%p), script(%p)", (RsContext)con, (RsScript)script);
     rsContextBindRootScript((RsContext)con, (RsScript)script);
 }
 
 static void
-nContextBindProgramStore(JNIEnv *_env, jobject _this, jlong con, jint pfs)
+nContextBindProgramStore(JNIEnv *_env, jobject _this, jlong con, jlong pfs)
 {
     LOG_API("nContextBindProgramStore, con(%p), pfs(%p)", (RsContext)con, (RsProgramStore)pfs);
     rsContextBindProgramStore((RsContext)con, (RsProgramStore)pfs);
 }
 
 static void
-nContextBindProgramFragment(JNIEnv *_env, jobject _this, jlong con, jint pf)
+nContextBindProgramFragment(JNIEnv *_env, jobject _this, jlong con, jlong pf)
 {
     LOG_API("nContextBindProgramFragment, con(%p), pf(%p)", (RsContext)con, (RsProgramFragment)pf);
     rsContextBindProgramFragment((RsContext)con, (RsProgramFragment)pf);
 }
 
 static void
-nContextBindProgramVertex(JNIEnv *_env, jobject _this, jlong con, jint pf)
+nContextBindProgramVertex(JNIEnv *_env, jobject _this, jlong con, jlong pf)
 {
     LOG_API("nContextBindProgramVertex, con(%p), pf(%p)", (RsContext)con, (RsProgramVertex)pf);
     rsContextBindProgramVertex((RsContext)con, (RsProgramVertex)pf);
 }
 
 static void
-nContextBindProgramRaster(JNIEnv *_env, jobject _this, jlong con, jint pf)
+nContextBindProgramRaster(JNIEnv *_env, jobject _this, jlong con, jlong pf)
 {
     LOG_API("nContextBindProgramRaster, con(%p), pf(%p)", (RsContext)con, (RsProgramRaster)pf);
     rsContextBindProgramRaster((RsContext)con, (RsProgramRaster)pf);
@@ -1416,24 +1471,36 @@
 }
 
 static jlong
-nMeshCreate(JNIEnv *_env, jobject _this, jlong con, jintArray _vtx, jintArray _idx, jintArray _prim)
+nMeshCreate(JNIEnv *_env, jobject _this, jlong con, jlongArray _vtx, jlongArray _idx, jintArray _prim)
 {
     LOG_API("nMeshCreate, con(%p)", (RsContext)con);
 
     jint vtxLen = _env->GetArrayLength(_vtx);
-    jint *vtxPtr = _env->GetIntArrayElements(_vtx, NULL);
+    jlong *jVtxPtr = _env->GetLongArrayElements(_vtx, NULL);
+    RsAllocation* vtxPtr = (RsAllocation*) malloc(sizeof(RsAllocation) * vtxLen);
+    for(int i = 0; i < vtxLen; ++i) {
+        vtxPtr[i] = (RsAllocation)(uintptr_t)jVtxPtr[i];
+    }
+
     jint idxLen = _env->GetArrayLength(_idx);
-    jint *idxPtr = _env->GetIntArrayElements(_idx, NULL);
+    jlong *jIdxPtr = _env->GetLongArrayElements(_idx, NULL);
+    RsAllocation* idxPtr = (RsAllocation*) malloc(sizeof(RsAllocation) * idxLen);
+    for(int i = 0; i < idxLen; ++i) {
+        idxPtr[i] = (RsAllocation)(uintptr_t)jIdxPtr[i];
+    }
+
     jint primLen = _env->GetArrayLength(_prim);
     jint *primPtr = _env->GetIntArrayElements(_prim, NULL);
 
-    int id = (int)rsMeshCreate((RsContext)con,
+    jlong id = (jlong)rsMeshCreate((RsContext)con,
                                (RsAllocation *)vtxPtr, vtxLen,
                                (RsAllocation *)idxPtr, idxLen,
                                (uint32_t *)primPtr, primLen);
 
-    _env->ReleaseIntArrayElements(_vtx, vtxPtr, 0);
-    _env->ReleaseIntArrayElements(_idx, idxPtr, 0);
+    free(vtxPtr);
+    free(idxPtr);
+    _env->ReleaseLongArrayElements(_vtx, jVtxPtr, 0);
+    _env->ReleaseLongArrayElements(_idx, jIdxPtr, 0);
     _env->ReleaseIntArrayElements(_prim, primPtr, 0);
     return id;
 }
@@ -1457,7 +1524,7 @@
 }
 
 static void
-nMeshGetVertices(JNIEnv *_env, jobject _this, jlong con, jlong mesh, jintArray _ids, int numVtxIDs)
+nMeshGetVertices(JNIEnv *_env, jobject _this, jlong con, jlong mesh, jlongArray _ids, jint numVtxIDs)
 {
     LOG_API("nMeshGetVertices, con(%p), Mesh(%p)", (RsContext)con, (RsMesh)mesh);
 
@@ -1465,14 +1532,15 @@
     rsaMeshGetVertices((RsContext)con, (RsMesh)mesh, allocs, (uint32_t)numVtxIDs);
 
     for(jint i = 0; i < numVtxIDs; i ++) {
-        _env->SetIntArrayRegion(_ids, i, 1, (const jint*)&allocs[i]);
+        const jlong alloc = (jlong)allocs[i];
+        _env->SetLongArrayRegion(_ids, i, 1, &alloc);
     }
 
     free(allocs);
 }
 
 static void
-nMeshGetIndices(JNIEnv *_env, jobject _this, jlong con, jlong mesh, jintArray _idxIds, jintArray _primitives, int numIndices)
+nMeshGetIndices(JNIEnv *_env, jobject _this, jlong con, jlong mesh, jlongArray _idxIds, jintArray _primitives, jint numIndices)
 {
     LOG_API("nMeshGetVertices, con(%p), Mesh(%p)", (RsContext)con, (RsMesh)mesh);
 
@@ -1482,8 +1550,10 @@
     rsaMeshGetIndices((RsContext)con, (RsMesh)mesh, allocs, prims, (uint32_t)numIndices);
 
     for(jint i = 0; i < numIndices; i ++) {
-        _env->SetIntArrayRegion(_idxIds, i, 1, (const jint*)&allocs[i]);
-        _env->SetIntArrayRegion(_primitives, i, 1, (const jint*)&prims[i]);
+        const jlong alloc = (jlong)allocs[i];
+        const jint prim = (jint)prims[i];
+        _env->SetLongArrayRegion(_idxIds, i, 1, &alloc);
+        _env->SetIntArrayRegion(_primitives, i, 1, &prim);
     }
 
     free(allocs);
@@ -1536,14 +1606,14 @@
 {"rsnFontCreateFromAsset",        "(JLandroid/content/res/AssetManager;Ljava/lang/String;FI)J",            (void*)nFontCreateFromAsset },
 
 {"rsnElementCreate",                 "(JJIZI)J",                              (void*)nElementCreate },
-{"rsnElementCreate2",                "(J[I[Ljava/lang/String;[I)J",           (void*)nElementCreate2 },
+{"rsnElementCreate2",                "(J[J[Ljava/lang/String;[I)J",           (void*)nElementCreate2 },
 {"rsnElementGetNativeData",          "(JJ[I)V",                               (void*)nElementGetNativeData },
-{"rsnElementGetSubElements",         "(JJ[I[Ljava/lang/String;[I)V",          (void*)nElementGetSubElements },
+{"rsnElementGetSubElements",         "(JJ[J[Ljava/lang/String;[I)V",          (void*)nElementGetSubElements },
 
 {"rsnTypeCreate",                    "(JJIIIZZI)J",                           (void*)nTypeCreate },
-{"rsnTypeGetNativeData",             "(JJ[I)V",                               (void*)nTypeGetNativeData },
+{"rsnTypeGetNativeData",             "(JJ[J)V",                               (void*)nTypeGetNativeData },
 
-{"rsnAllocationCreateTyped",         "(JJIII)J",                               (void*)nAllocationCreateTyped },
+{"rsnAllocationCreateTyped",         "(JJIIJ)J",                               (void*)nAllocationCreateTyped },
 {"rsnAllocationCreateFromBitmap",    "(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCreateFromBitmap },
 {"rsnAllocationCreateBitmapBackedAllocation",    "(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCreateBitmapBackedAllocation },
 {"rsnAllocationCubeCreateFromBitmap","(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCubeCreateFromBitmap },
@@ -1594,7 +1664,7 @@
 {"rsnScriptIntrinsicCreate",         "(JIJ)J",                                (void*)nScriptIntrinsicCreate },
 {"rsnScriptKernelIDCreate",          "(JJII)J",                               (void*)nScriptKernelIDCreate },
 {"rsnScriptFieldIDCreate",           "(JJI)J",                                (void*)nScriptFieldIDCreate },
-{"rsnScriptGroupCreate",             "(J[I[I[I[I[I)J",                        (void*)nScriptGroupCreate },
+{"rsnScriptGroupCreate",             "(J[J[J[J[J[J)J",                        (void*)nScriptGroupCreate },
 {"rsnScriptGroupSetInput",           "(JJJJ)V",                               (void*)nScriptGroupSetInput },
 {"rsnScriptGroupSetOutput",          "(JJJJ)V",                               (void*)nScriptGroupSetOutput },
 {"rsnScriptGroupExecute",            "(JJ)V",                                 (void*)nScriptGroupExecute },
@@ -1605,25 +1675,25 @@
 {"rsnProgramBindTexture",            "(JJIJ)V",                               (void*)nProgramBindTexture },
 {"rsnProgramBindSampler",            "(JJIJ)V",                               (void*)nProgramBindSampler },
 
-{"rsnProgramFragmentCreate",         "(JLjava/lang/String;[Ljava/lang/String;[I)J",              (void*)nProgramFragmentCreate },
+{"rsnProgramFragmentCreate",         "(JLjava/lang/String;[Ljava/lang/String;[J)J",              (void*)nProgramFragmentCreate },
 {"rsnProgramRasterCreate",           "(JZI)J",                                (void*)nProgramRasterCreate },
-{"rsnProgramVertexCreate",           "(JLjava/lang/String;[Ljava/lang/String;[I)J",              (void*)nProgramVertexCreate },
+{"rsnProgramVertexCreate",           "(JLjava/lang/String;[Ljava/lang/String;[J)J",              (void*)nProgramVertexCreate },
 
-{"rsnContextBindRootScript",         "(JI)V",                                 (void*)nContextBindRootScript },
-{"rsnContextBindProgramStore",       "(JI)V",                                 (void*)nContextBindProgramStore },
-{"rsnContextBindProgramFragment",    "(JI)V",                                 (void*)nContextBindProgramFragment },
-{"rsnContextBindProgramVertex",      "(JI)V",                                 (void*)nContextBindProgramVertex },
-{"rsnContextBindProgramRaster",      "(JI)V",                                 (void*)nContextBindProgramRaster },
+{"rsnContextBindRootScript",         "(JJ)V",                                 (void*)nContextBindRootScript },
+{"rsnContextBindProgramStore",       "(JJ)V",                                 (void*)nContextBindProgramStore },
+{"rsnContextBindProgramFragment",    "(JJ)V",                                 (void*)nContextBindProgramFragment },
+{"rsnContextBindProgramVertex",      "(JJ)V",                                 (void*)nContextBindProgramVertex },
+{"rsnContextBindProgramRaster",      "(JJ)V",                                 (void*)nContextBindProgramRaster },
 
 {"rsnSamplerCreate",                 "(JIIIIIF)J",                            (void*)nSamplerCreate },
 
 {"rsnPathCreate",                    "(JIZJJF)J",                             (void*)nPathCreate },
-{"rsnMeshCreate",                    "(J[I[I[I)J",                            (void*)nMeshCreate },
+{"rsnMeshCreate",                    "(J[J[J[I)J",                            (void*)nMeshCreate },
 
 {"rsnMeshGetVertexBufferCount",      "(JJ)I",                                 (void*)nMeshGetVertexBufferCount },
 {"rsnMeshGetIndexCount",             "(JJ)I",                                 (void*)nMeshGetIndexCount },
-{"rsnMeshGetVertices",               "(JJ[II)V",                              (void*)nMeshGetVertices },
-{"rsnMeshGetIndices",                "(JJ[I[II)V",                            (void*)nMeshGetIndices },
+{"rsnMeshGetVertices",               "(JJ[JI)V",                              (void*)nMeshGetVertices },
+{"rsnMeshGetIndices",                "(JJ[J[II)V",                            (void*)nMeshGetIndices },
 
 };
 
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index 2e1b0af..defc6ef 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -669,12 +669,19 @@
         }
     }
 
-    public void setTime(long millis) {
+    public boolean setTime(long millis) {
         mContext.enforceCallingOrSelfPermission(
                 "android.permission.SET_TIME",
                 "setTime");
 
-        SystemClock.setCurrentTimeMillis(millis);
+        if (mNativeData == 0) {
+            Slog.w(TAG, "Not setting time since no alarm driver is available.");
+            return false;
+        }
+
+        synchronized (mLock) {
+            return setKernelTime(mNativeData, millis) == 0;
+        }
     }
 
     public void setTimeZone(String tz) {
@@ -1018,6 +1025,7 @@
     private native void close(long nativeData);
     private native void set(long nativeData, int type, long seconds, long nanoseconds);
     private native int waitForAlarm(long nativeData);
+    private native int setKernelTime(long nativeData, long millis);
     private native int setKernelTimezone(long nativeData, int minuteswest);
 
     private void triggerAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED, long nowRTC) {
diff --git a/services/java/com/android/server/AssetAtlasService.java b/services/java/com/android/server/AssetAtlasService.java
index 3fb006b..fc4838c 100644
--- a/services/java/com/android/server/AssetAtlasService.java
+++ b/services/java/com/android/server/AssetAtlasService.java
@@ -114,12 +114,11 @@
 
     // Describes how bitmaps are placed in the atlas. Each bitmap is
     // represented by several entries in the array:
-    // int0: SkBitmap*, the native bitmap object
-    // int1: x position
-    // int2: y position
-    // int3: rotated, 1 if the bitmap must be rotated, 0 otherwise
-    // NOTE: This will need to be handled differently to support 64 bit pointers
-    private int[] mAtlasMap;
+    // long0: SkBitmap*, the native bitmap object
+    // long1: x position
+    // long2: y position
+    // long3: rotated, 1 if the bitmap must be rotated, 0 otherwise
+    private long[] mAtlasMap;
 
     /**
      * Creates a new service. Upon creating, the service will gather the list of
@@ -196,7 +195,7 @@
         private final ArrayList<Bitmap> mBitmaps;
         private final int mPixelCount;
 
-        private int mNativeBitmap;
+        private long mNativeBitmap;
 
         // Used for debugging only
         private Bitmap mAtlasBitmap;
@@ -260,8 +259,8 @@
 
             final Atlas.Entry entry = new Atlas.Entry();
 
-            mAtlasMap = new int[packCount * ATLAS_MAP_ENTRY_FIELD_COUNT];
-            int[] atlasMap = mAtlasMap;
+            mAtlasMap = new long[packCount * ATLAS_MAP_ENTRY_FIELD_COUNT];
+            long[] atlasMap = mAtlasMap;
             int mapIndex = 0;
 
             boolean result = false;
@@ -288,8 +287,7 @@
                         }
                         canvas.drawBitmap(bitmap, 0.0f, 0.0f, null);
                         canvas.restore();
-                        // TODO: Change mAtlasMap to long[] to support 64-bit systems
-                        atlasMap[mapIndex++] = (int) bitmap.mNativeBitmap;
+                        atlasMap[mapIndex++] = bitmap.mNativeBitmap;
                         atlasMap[mapIndex++] = entry.x;
                         atlasMap[mapIndex++] = entry.y;
                         atlasMap[mapIndex++] = entry.rotated ? 1 : 0;
@@ -365,9 +363,9 @@
         }
     }
 
-    private static native int nAcquireAtlasCanvas(Canvas canvas, int width, int height);
-    private static native void nReleaseAtlasCanvas(Canvas canvas, int bitmap);
-    private static native boolean nUploadAtlas(GraphicBuffer buffer, int bitmap);
+    private static native long nAcquireAtlasCanvas(Canvas canvas, int width, int height);
+    private static native void nReleaseAtlasCanvas(Canvas canvas, long bitmap);
+    private static native boolean nUploadAtlas(GraphicBuffer buffer, long bitmap);
 
     @Override
     public boolean isCompatible(int ppid) {
@@ -380,7 +378,7 @@
     }
 
     @Override
-    public int[] getMap() throws RemoteException {
+    public long[] getMap() throws RemoteException {
         return mAtlasReady.get() ? mAtlasMap : null;
     }
 
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 8f480dd..b4a982e 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -452,6 +452,9 @@
      * @param userId the new active user's UserId
      */
     private void switchUser(int userId) {
+        if (mCurrentUserId == userId) {
+            return;
+        }
         mBlacklist.switchUser(userId);
         mLocationHandler.removeMessages(MSG_LOCATION_CHANGED);
         synchronized (mLock) {
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 816ae69..f73a92b 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -91,6 +91,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -384,18 +385,37 @@
     }
 
     class ShutdownCallBack extends UnmountCallBack {
-        IMountShutdownObserver observer;
-        ShutdownCallBack(String path, IMountShutdownObserver observer) {
+        MountShutdownLatch mMountShutdownLatch;
+        ShutdownCallBack(String path, final MountShutdownLatch mountShutdownLatch) {
             super(path, true, false);
-            this.observer = observer;
+            mMountShutdownLatch = mountShutdownLatch;
         }
 
         @Override
         void handleFinished() {
             int ret = doUnmountVolume(path, true, removeEncryption);
-            if (observer != null) {
+            Slog.i(TAG, "Unmount completed: " + path + ", result code: " + ret);
+            mMountShutdownLatch.countDown();
+        }
+    }
+
+    static class MountShutdownLatch {
+        private IMountShutdownObserver mObserver;
+        private AtomicInteger mCount;
+
+        MountShutdownLatch(final IMountShutdownObserver observer, int count) {
+            mObserver = observer;
+            mCount = new AtomicInteger(count);
+        }
+
+        void countDown() {
+            boolean sendShutdown = false;
+            if (mCount.decrementAndGet() == 0) {
+                sendShutdown = true;
+            }
+            if (sendShutdown && mObserver != null) {
                 try {
-                    observer.onShutDownComplete(ret);
+                    mObserver.onShutDownComplete(StorageResultCode.OperationSucceeded);
                 } catch (RemoteException e) {
                     Slog.w(TAG, "RemoteException when shutting down");
                 }
@@ -1426,6 +1446,10 @@
 
         Slog.i(TAG, "Shutting down");
         synchronized (mVolumesLock) {
+            // Get all volumes to be unmounted.
+            MountShutdownLatch mountShutdownLatch = new MountShutdownLatch(observer,
+                                                            mVolumeStates.size());
+
             for (String path : mVolumeStates.keySet()) {
                 String state = mVolumeStates.get(path);
 
@@ -1461,19 +1485,16 @@
 
                 if (state.equals(Environment.MEDIA_MOUNTED)) {
                     // Post a unmount message.
-                    ShutdownCallBack ucb = new ShutdownCallBack(path, observer);
+                    ShutdownCallBack ucb = new ShutdownCallBack(path, mountShutdownLatch);
                     mHandler.sendMessage(mHandler.obtainMessage(H_UNMOUNT_PM_UPDATE, ucb));
                 } else if (observer != null) {
                     /*
-                     * Observer is waiting for onShutDownComplete when we are done.
-                     * Since nothing will be done send notification directly so shutdown
-                     * sequence can continue.
+                     * Count down, since nothing will be done. The observer will be
+                     * notified when we are done so shutdown sequence can continue.
                      */
-                    try {
-                        observer.onShutDownComplete(StorageResultCode.OperationSucceeded);
-                    } catch (RemoteException e) {
-                        Slog.w(TAG, "RemoteException when shutting down");
-                    }
+                    mountShutdownLatch.countDown();
+                    Slog.i(TAG, "Unmount completed: " + path +
+                        ", result code: " + StorageResultCode.OperationSucceeded);
                 }
             }
         }
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index ad7ec99..e6c5422 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -82,6 +82,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.StringTokenizer;
@@ -1022,6 +1023,15 @@
         }
     }
 
+    private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) {
+        ArrayList<InterfaceAddress> filtered = new ArrayList<InterfaceAddress>(addresses.size());
+        for (InterfaceAddress ia : addresses) {
+            if (!ia.getAddress().isLinkLocalAddress())
+                filtered.add(ia);
+        }
+        return filtered;
+    }
+
     private void modifyNat(String action, String internalInterface, String externalInterface)
             throws SocketException {
         final Command cmd = new Command("nat", action, internalInterface, externalInterface);
@@ -1031,8 +1041,10 @@
         if (internalNetworkInterface == null) {
             cmd.appendArg("0");
         } else {
-            Collection<InterfaceAddress> interfaceAddresses = internalNetworkInterface
-                    .getInterfaceAddresses();
+            // Don't touch link-local routes, as link-local addresses aren't routable,
+            // kernel creates link-local routes on all interfaces automatically
+            List<InterfaceAddress> interfaceAddresses = excludeLinkLocal(
+                    internalNetworkInterface.getInterfaceAddresses());
             cmd.appendArg(interfaceAddresses.size());
             for (InterfaceAddress ia : interfaceAddresses) {
                 InetAddress addr = NetworkUtils.getNetworkPart(
diff --git a/services/java/com/android/server/NsdService.java b/services/java/com/android/server/NsdService.java
index 16d2468..9379955 100644
--- a/services/java/com/android/server/NsdService.java
+++ b/services/java/com/android/server/NsdService.java
@@ -152,25 +152,40 @@
         class DefaultState extends State {
             @Override
             public boolean processMessage(Message msg) {
+                ClientInfo cInfo = null;
                 switch (msg.what) {
                     case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
                         if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
                             AsyncChannel c = (AsyncChannel) msg.obj;
                             if (DBG) Slog.d(TAG, "New client listening to asynchronous messages");
                             c.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED);
-                            ClientInfo cInfo = new ClientInfo(c, msg.replyTo);
+                            cInfo = new ClientInfo(c, msg.replyTo);
                             mClients.put(msg.replyTo, cInfo);
                         } else {
                             Slog.e(TAG, "Client connection failure, error=" + msg.arg1);
                         }
                         break;
                     case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
-                        if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
-                            Slog.e(TAG, "Send failed, client connection lost");
-                        } else {
-                            if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1);
+                        switch (msg.arg1) {
+                            case AsyncChannel.STATUS_SEND_UNSUCCESSFUL:
+                                Slog.e(TAG, "Send failed, client connection lost");
+                                break;
+                            case AsyncChannel.STATUS_REMOTE_DISCONNECTION:
+                                if (DBG) Slog.d(TAG, "Client disconnected");
+                                break;
+                            default:
+                                if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1);
+                                break;
                         }
-                        mClients.remove(msg.replyTo);
+                        cInfo = mClients.get(msg.replyTo);
+                        if (cInfo != null) {
+                            cInfo.expungeAllRequests();
+                            mClients.remove(msg.replyTo);
+                        }
+                        //Last client
+                        if (mClients.size() == 0) {
+                            stopMDnsDaemon();
+                        }
                         break;
                     case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
                         AsyncChannel ac = new AsyncChannel();
@@ -248,13 +263,15 @@
                 return false;
             }
 
-            private void storeRequestMap(int clientId, int globalId, ClientInfo clientInfo) {
+            private void storeRequestMap(int clientId, int globalId, ClientInfo clientInfo, int what) {
                 clientInfo.mClientIds.put(clientId, globalId);
+                clientInfo.mClientRequests.put(clientId, what);
                 mIdToClientInfoMap.put(globalId, clientInfo);
             }
 
             private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) {
                 clientInfo.mClientIds.remove(clientId);
+                clientInfo.mClientRequests.remove(clientId);
                 mIdToClientInfoMap.remove(globalId);
             }
 
@@ -274,10 +291,6 @@
                         result = NOT_HANDLED;
                         break;
                     case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
-                        //Last client
-                        if (mClients.size() == 1) {
-                            stopMDnsDaemon();
-                        }
                         result = NOT_HANDLED;
                         break;
                     case NsdManager.DISABLE:
@@ -301,7 +314,7 @@
                                 Slog.d(TAG, "Discover " + msg.arg2 + " " + id +
                                         servInfo.getServiceType());
                             }
-                            storeRequestMap(msg.arg2, id, clientInfo);
+                            storeRequestMap(msg.arg2, id, clientInfo, msg.what);
                             replyToMessage(msg, NsdManager.DISCOVER_SERVICES_STARTED, servInfo);
                         } else {
                             stopServiceDiscovery(id);
@@ -340,7 +353,7 @@
                         id = getUniqueId();
                         if (registerService(id, (NsdServiceInfo) msg.obj)) {
                             if (DBG) Slog.d(TAG, "Register " + msg.arg2 + " " + id);
-                            storeRequestMap(msg.arg2, id, clientInfo);
+                            storeRequestMap(msg.arg2, id, clientInfo, msg.what);
                             // Return success after mDns reports success
                         } else {
                             unregisterService(id);
@@ -381,7 +394,7 @@
                         id = getUniqueId();
                         if (resolveService(id, servInfo)) {
                             clientInfo.mResolvedService = new NsdServiceInfo();
-                            storeRequestMap(msg.arg2, id, clientInfo);
+                            storeRequestMap(msg.arg2, id, clientInfo, msg.what);
                         } else {
                             replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED,
                                     NsdManager.FAILURE_INTERNAL_ERROR);
@@ -487,7 +500,7 @@
 
                         int id2 = getUniqueId();
                         if (getAddrInfo(id2, cooked[3])) {
-                            storeRequestMap(clientId, id2, clientInfo);
+                            storeRequestMap(clientId, id2, clientInfo, NsdManager.RESOLVE_SERVICE);
                         } else {
                             clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED,
                                     NsdManager.FAILURE_INTERNAL_ERROR, clientId);
@@ -827,6 +840,9 @@
         /* A map from client id to unique id sent to mDns */
         private SparseArray<Integer> mClientIds = new SparseArray<Integer>();
 
+        /* A map from client id to the type of the request we had received */
+        private SparseArray<Integer> mClientRequests = new SparseArray<Integer>();
+
         private ClientInfo(AsyncChannel c, Messenger m) {
             mChannel = c;
             mMessenger = m;
@@ -840,10 +856,41 @@
             sb.append("mMessenger ").append(mMessenger).append("\n");
             sb.append("mResolvedService ").append(mResolvedService).append("\n");
             for(int i = 0; i< mClientIds.size(); i++) {
-                sb.append("clientId ").append(mClientIds.keyAt(i));
-                sb.append(" mDnsId ").append(mClientIds.valueAt(i)).append("\n");
+                int clientID = mClientIds.keyAt(i);
+                sb.append("clientId ").append(clientID).
+                    append(" mDnsId ").append(mClientIds.valueAt(i)).
+                    append(" type ").append(mClientRequests.get(clientID)).append("\n");
             }
             return sb.toString();
         }
+
+        // Remove any pending requests from the global map when we get rid of a client,
+        // and send cancellations to the daemon.
+        private void expungeAllRequests() {
+            int globalId, clientId, i;
+            for (i = 0; i < mClientIds.size(); i++) {
+                clientId = mClientIds.keyAt(i);
+                globalId = mClientIds.valueAt(i);
+                mIdToClientInfoMap.remove(globalId);
+                if (DBG) Slog.d(TAG, "Terminating client-ID " + clientId +
+                        " global-ID " + globalId + " type " + mClientRequests.get(clientId));
+                switch (mClientRequests.get(clientId)) {
+                    case NsdManager.DISCOVER_SERVICES:
+                        stopServiceDiscovery(globalId);
+                        break;
+                    case NsdManager.RESOLVE_SERVICE:
+                        stopResolveService(globalId);
+                        break;
+                    case NsdManager.REGISTER_SERVICE:
+                        unregisterService(globalId);
+                        break;
+                    default:
+                        break;
+                }
+            }
+            mClientIds.clear();
+            mClientRequests.clear();
+        }
+
     }
 }
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
old mode 100644
new mode 100755
index 933247e..e06b8c5
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -203,6 +203,7 @@
                     Slog.i(TAG, "Waited long enough for: " + r);
                     mStartingBackground.remove(i);
                     N--;
+                    i--;
                 }
             }
             while (mDelayedStartList.size() > 0
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index fc66e45..97696a5 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1058,6 +1058,7 @@
     static final int IMMERSIVE_MODE_LOCK_MSG = 37;
     static final int PERSIST_URI_GRANTS_MSG = 38;
     static final int REQUEST_ALL_PSS_MSG = 39;
+    static final int UPDATE_TIME = 40;
 
     static final int FIRST_ACTIVITY_STACK_MSG = 100;
     static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1668,6 +1669,22 @@
                 requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false);
                 break;
             }
+            case UPDATE_TIME: {
+                synchronized (ActivityManagerService.this) {
+                    for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
+                        ProcessRecord r = mLruProcesses.get(i);
+                        if (r.thread != null) {
+                            try {
+                                r.thread.updateTimePrefs(msg.arg1 == 0 ? false : true);
+                            } catch (RemoteException ex) {
+                                Slog.w(TAG, "Failed to update preferences for: " + r.info.processName);
+                            }
+                        }
+                    }
+                }
+
+                break;
+            }
             }
         }
     };
@@ -12418,6 +12435,7 @@
         app.foregroundActivities = false;
         app.hasShownUi = false;
         app.hasAboveClient = false;
+        app.hasClientActivities = false;
 
         mServices.killServicesLocked(app, allowRestart);
 
@@ -13430,11 +13448,20 @@
          * of all currently running processes. This message will get queued up before the broadcast
          * happens.
          */
-        if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
+        if (Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
             mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
         }
 
-        if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
+        /*
+         * If the user set the time, let all running processes know.
+         */
+        if (Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) {
+            final int is24Hour = intent.getBooleanExtra(
+                    Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, false) ? 1 : 0;
+            mHandler.sendMessage(mHandler.obtainMessage(UPDATE_TIME, is24Hour, 0));
+        }
+
+        if (Intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
             mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG);
         }
 
diff --git a/services/java/com/android/server/am/CoreSettingsObserver.java b/services/java/com/android/server/am/CoreSettingsObserver.java
index 10ea67c..4c887dd 100644
--- a/services/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/java/com/android/server/am/CoreSettingsObserver.java
@@ -37,11 +37,16 @@
     private static final String LOG_TAG = CoreSettingsObserver.class.getSimpleName();
 
     // mapping form property name to its type
-    private static final Map<String, Class<?>> sCoreSettingToTypeMap = new HashMap<
+    private static final Map<String, Class<?>> sSecureSettingToTypeMap = new HashMap<
+            String, Class<?>>();
+    private static final Map<String, Class<?>> sSystemSettingToTypeMap = new HashMap<
             String, Class<?>>();
     static {
-        sCoreSettingToTypeMap.put(Settings.Secure.LONG_PRESS_TIMEOUT, int.class);
-        // add other core settings here...
+        sSecureSettingToTypeMap.put(Settings.Secure.LONG_PRESS_TIMEOUT, int.class);
+        // add other secure settings here...
+
+        sSystemSettingToTypeMap.put(Settings.System.TIME_12_24, String.class);
+        // add other system settings here...
     }
 
     private final Bundle mCoreSettings = new Bundle();
@@ -67,39 +72,62 @@
     }
 
     private void sendCoreSettings() {
-        populateCoreSettings(mCoreSettings);
+        populateSettings(mCoreSettings, sSecureSettingToTypeMap);
+        populateSettings(mCoreSettings, sSystemSettingToTypeMap);
         mActivityManagerService.onCoreSettingsChange(mCoreSettings);
     }
 
     private void beginObserveCoreSettings() {
-        for (String setting : sCoreSettingToTypeMap.keySet()) {
+        for (String setting : sSecureSettingToTypeMap.keySet()) {
             Uri uri = Settings.Secure.getUriFor(setting);
             mActivityManagerService.mContext.getContentResolver().registerContentObserver(
                     uri, false, this);
         }
+
+        for (String setting : sSystemSettingToTypeMap.keySet()) {
+            Uri uri = Settings.System.getUriFor(setting);
+            mActivityManagerService.mContext.getContentResolver().registerContentObserver(
+                    uri, false, this);
+        }
     }
 
-    private void populateCoreSettings(Bundle snapshot) {
+    private void populateSettings(Bundle snapshot, Map<String, Class<?>> map) {
         Context context = mActivityManagerService.mContext;
-        for (Map.Entry<String, Class<?>> entry : sCoreSettingToTypeMap.entrySet()) {
+        for (Map.Entry<String, Class<?>> entry : map.entrySet()) {
             String setting = entry.getKey();
             Class<?> type = entry.getValue();
             try {
                 if (type == String.class) {
-                    String value = Settings.Secure.getString(context.getContentResolver(),
-                            setting);
+                    final String value;
+                    if (map == sSecureSettingToTypeMap) {
+                        value = Settings.Secure.getString(context.getContentResolver(), setting);
+                    } else {
+                        value = Settings.System.getString(context.getContentResolver(), setting);
+                    }
                     snapshot.putString(setting, value);
                 } else if (type == int.class) {
-                    int value = Settings.Secure.getInt(context.getContentResolver(),
-                            setting);
+                    final int value;
+                    if (map == sSecureSettingToTypeMap) {
+                        value = Settings.Secure.getInt(context.getContentResolver(), setting);
+                    } else {
+                        value = Settings.System.getInt(context.getContentResolver(), setting);
+                    }
                     snapshot.putInt(setting, value);
                 } else if (type == float.class) {
-                    float value = Settings.Secure.getFloat(context.getContentResolver(),
-                            setting);
+                    final float value;
+                    if (map == sSecureSettingToTypeMap) {
+                        value = Settings.Secure.getFloat(context.getContentResolver(), setting);
+                    } else {
+                        value = Settings.System.getFloat(context.getContentResolver(), setting);
+                    }
                     snapshot.putFloat(setting, value);
                 } else if (type == long.class) {
-                    long value = Settings.Secure.getLong(context.getContentResolver(),
-                            setting);
+                    final long value;
+                    if (map == sSecureSettingToTypeMap) {
+                        value = Settings.Secure.getLong(context.getContentResolver(), setting);
+                    } else {
+                        value = Settings.System.getLong(context.getContentResolver(), setting);
+                    }
                     snapshot.putLong(setting, value);
                 }
             } catch (SettingNotFoundException snfe) {
diff --git a/services/java/com/android/server/firewall/IntentFirewall.java b/services/java/com/android/server/firewall/IntentFirewall.java
index aaa0b58..6df1dbd 100644
--- a/services/java/com/android/server/firewall/IntentFirewall.java
+++ b/services/java/com/android/server/firewall/IntentFirewall.java
@@ -268,11 +268,13 @@
         }
 
         File[] files = rulesDir.listFiles();
-        for (int i=0; i<files.length; i++) {
-            File file = files[i];
+        if (files != null) {
+            for (int i=0; i<files.length; i++) {
+                File file = files[i];
 
-            if (file.getName().endsWith(".xml")) {
-                readRules(file, resolvers);
+                if (file.getName().endsWith(".xml")) {
+                    readRules(file, resolvers);
+                }
             }
         }
 
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index 11a6498..4b087cc 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -208,6 +208,19 @@
         builder.append(' ');
         builder.append(uid);
         builder.append(isPublic ? " 1" : " 0");
+        builder.append(" *");         // No pkgName arg present
+        return execute(builder.toString());
+    }
+
+    public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName) {
+        StringBuilder builder = new StringBuilder("dexopt");
+        builder.append(' ');
+        builder.append(apkPath);
+        builder.append(' ');
+        builder.append(uid);
+        builder.append(isPublic ? " 1" : " 0");
+        builder.append(' ');
+        builder.append(pkgName);
         return execute(builder.toString());
     }
 
@@ -383,4 +396,8 @@
 
         return execute(builder.toString());
     }
+
+    public boolean restoreconData() {
+        return (execute("restorecondata") == 0);
+    }
 }
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 74a66d6..5dded57 100755
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -1209,7 +1209,7 @@
                         continue;
                     }
                     try {
-                        if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
+                        if (dalvik.system.DexFile.isDexOptNeededInternal(lib, null, false)) {
                             alreadyDexOpted.add(lib);
                             mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
                             didDexOpt = true;
@@ -1253,7 +1253,7 @@
                         continue;
                     }
                     try {
-                        if (dalvik.system.DexFile.isDexOptNeeded(path)) {
+                        if (dalvik.system.DexFile.isDexOptNeededInternal(path, null, false)) {
                             mInstaller.dexopt(path, Process.SYSTEM_UID, true);
                             didDexOpt = true;
                         }
@@ -1486,6 +1486,13 @@
             // can downgrade to reader
             mSettings.writeLPr();
 
+            if (SELinuxMMAC.shouldRestorecon()) {
+                Slog.i(TAG, "Relabeling of /data/data and /data/user issued.");
+                if (mInstaller.restoreconData()) {
+                    SELinuxMMAC.setRestoreconDone();
+                }
+            }
+
             EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
                     SystemClock.uptimeMillis());
 
@@ -3674,6 +3681,7 @@
             updatedPkg = mSettings.getDisabledSystemPkgLPr(ps != null ? ps.name : pkg.packageName);
             if (DEBUG_INSTALL && updatedPkg != null) Slog.d(TAG, "updatedPkg = " + updatedPkg);
         }
+        boolean updatedPkgBetter = false;
         // First check if this is a system package that may involve an update
         if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
             if (ps != null && !ps.codePath.equals(scanFile)) {
@@ -3728,6 +3736,7 @@
                     synchronized (mPackages) {
                         mSettings.enableSystemPackageLPw(ps.name);
                     }
+                    updatedPkgBetter = true;
                 }
             }
         }
@@ -3804,7 +3813,7 @@
 
         String codePath = null;
         String resPath = null;
-        if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
+        if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !updatedPkgBetter) {
             if (ps != null && ps.resourcePathString != null) {
                 resPath = ps.resourcePathString;
             } else {
@@ -3986,7 +3995,8 @@
             String path = pkg.mScanPath;
             int ret = 0;
             try {
-                if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
+                if (forceDex || dalvik.system.DexFile.isDexOptNeededInternal(path, pkg.packageName,
+                                                                             defer)) {
                     if (!forceDex && defer) {
                         if (mDeferredDexOpt == null) {
                             mDeferredDexOpt = new HashSet<PackageParser.Package>();
@@ -3996,7 +4006,8 @@
                     } else {
                         Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName);
                         final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
-                        ret = mInstaller.dexopt(path, sharedGid, !isForwardLocked(pkg));
+                        ret = mInstaller.dexopt(path, sharedGid, !isForwardLocked(pkg),
+                                                pkg.packageName);
                         pkg.mDidDexOpt = true;
                         performed = true;
                     }
diff --git a/services/java/com/android/server/pm/SELinuxMMAC.java b/services/java/com/android/server/pm/SELinuxMMAC.java
index 1d68afa..af7153f 100644
--- a/services/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/java/com/android/server/pm/SELinuxMMAC.java
@@ -25,11 +25,16 @@
 
 import com.android.internal.util.XmlUtils;
 
+import libcore.io.IoUtils;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 
 import java.util.HashMap;
 
@@ -60,6 +65,13 @@
         new File(Environment.getRootDirectory(), "etc/security/mac_permissions.xml"),
         null};
 
+    // Location of seapp_contexts policy file.
+    private static final String SEAPP_CONTEXTS_FILE = "/seapp_contexts";
+
+    // Stores the hash of the last used seapp_contexts file.
+    private static final String SEAPP_HASH_FILE =
+            Environment.getDataDirectory().toString() + "/system/seapp_hash";
+
     // Signature policy stanzas
     static class Policy {
         private String seinfo;
@@ -103,7 +115,6 @@
 
     /**
      * Parses an MMAC install policy from a predefined list of locations.
-     * @param none
      * @return boolean indicating whether an install policy was correctly parsed.
      */
     public static boolean readInstallPolicy() {
@@ -113,7 +124,7 @@
 
     /**
      * Parses an MMAC install policy given as an argument.
-     * @param File object representing the path of the policy.
+     * @param policyFile object representing the path of the policy.
      * @return boolean indicating whether the install policy was correctly parsed.
      */
     public static boolean readInstallPolicy(File policyFile) {
@@ -345,8 +356,7 @@
     /**
      * Labels a package based on an seinfo tag from install policy.
      * The label is attached to the ApplicationInfo instance of the package.
-     * @param PackageParser.Package object representing the package
-     *         to labeled.
+     * @param pkg object representing the package to be labeled.
      * @return boolean which determines whether a non null seinfo label
      *         was assigned to the package. A null value simply meaning that
      *         no policy matched.
@@ -391,4 +401,89 @@
 
         return (sDefaultSeinfo != null);
     }
+
+    /**
+     * Determines if a recursive restorecon on /data/data and /data/user is needed.
+     * It does this by comparing the SHA-1 of the seapp_contexts file against the
+     * stored hash at /data/system/seapp_hash.
+     *
+     * @return Returns true if the restorecon should occur or false otherwise.
+     */
+    public static boolean shouldRestorecon() {
+        // Any error with the seapp_contexts file should be fatal
+        byte[] currentHash = null;
+        try {
+            currentHash = returnHash(SEAPP_CONTEXTS_FILE);
+        } catch (IOException ioe) {
+            Slog.e(TAG, "Error with hashing seapp_contexts.", ioe);
+            return false;
+        }
+
+        // Push past any error with the stored hash file
+        byte[] storedHash = null;
+        try {
+            storedHash = IoUtils.readFileAsByteArray(SEAPP_HASH_FILE);
+        } catch (IOException ioe) {
+            Slog.w(TAG, "Error opening " + SEAPP_HASH_FILE + ". Assuming first boot.");
+        }
+
+        return (storedHash == null || !MessageDigest.isEqual(storedHash, currentHash));
+    }
+
+    /**
+     * Stores the SHA-1 of the seapp_contexts to /data/system/seapp_hash.
+     */
+    public static void setRestoreconDone() {
+        try {
+            final byte[] currentHash = returnHash(SEAPP_CONTEXTS_FILE);
+            dumpHash(new File(SEAPP_HASH_FILE), currentHash);
+        } catch (IOException ioe) {
+            Slog.e(TAG, "Error with saving hash to " + SEAPP_HASH_FILE, ioe);
+        }
+    }
+
+    /**
+     * Dump the contents of a byte array to a specified file.
+     *
+     * @param file The file that receives the byte array content.
+     * @param content A byte array that will be written to the specified file.
+     * @throws IOException if any failed I/O operation occured.
+     *         Included is the failure to atomically rename the tmp
+     *         file used in the process.
+     */
+    private static void dumpHash(File file, byte[] content) throws IOException {
+        FileOutputStream fos = null;
+        File tmp = null;
+        try {
+            tmp = File.createTempFile("seapp_hash", ".journal", file.getParentFile());
+            tmp.setReadable(true);
+            fos = new FileOutputStream(tmp);
+            fos.write(content);
+            fos.getFD().sync();
+            if (!tmp.renameTo(file)) {
+                throw new IOException("Failure renaming " + file.getCanonicalPath());
+            }
+        } finally {
+            if (tmp != null) {
+                tmp.delete();
+            }
+            IoUtils.closeQuietly(fos);
+        }
+    }
+
+    /**
+     * Return the SHA-1 of a file.
+     *
+     * @param file The path to the file given as a string.
+     * @return Returns the SHA-1 of the file as a byte array.
+     * @throws IOException if any failed I/O operations occured.
+     */
+    private static byte[] returnHash(String file) throws IOException {
+        try {
+            final byte[] contents = IoUtils.readFileAsByteArray(file);
+            return MessageDigest.getInstance("SHA-1").digest(contents);
+        } catch (NoSuchAlgorithmException nsae) {
+            throw new RuntimeException(nsae);  // impossible
+        }
+    }
 }
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 6d47fcf..5da3e3e 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -3480,8 +3480,9 @@
             Task newTask = mTaskIdToTask.get(groupId);
             if (newTask == null) {
                 newTask = createTask(groupId, oldTask.mStack.mStackId, oldTask.mUserId, atoken);
+            } else {
+                newTask.mAppTokens.add(atoken);
             }
-            newTask.mAppTokens.add(atoken);
         }
     }
 
diff --git a/services/jni/com_android_server_AlarmManagerService.cpp b/services/jni/com_android_server_AlarmManagerService.cpp
index 342515b..c26a516 100644
--- a/services/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/jni/com_android_server_AlarmManagerService.cpp
@@ -36,6 +36,7 @@
 #include <unistd.h>
 #include <linux/ioctl.h>
 #include <linux/android_alarm.h>
+#include <linux/rtc.h>
 
 namespace android {
 
@@ -58,6 +59,7 @@
     virtual ~AlarmImpl();
 
     virtual int set(int type, struct timespec *ts) = 0;
+    virtual int setTime(struct timeval *tv) = 0;
     virtual int waitForAlarm() = 0;
 
 protected:
@@ -71,6 +73,7 @@
     AlarmImplAlarmDriver(int fd) : AlarmImpl(&fd, 1) { }
 
     int set(int type, struct timespec *ts);
+    int setTime(struct timeval *tv);
     int waitForAlarm();
 };
 
@@ -82,6 +85,7 @@
     ~AlarmImplTimerFd();
 
     int set(int type, struct timespec *ts);
+    int setTime(struct timeval *tv);
     int waitForAlarm();
 
 private:
@@ -107,6 +111,19 @@
     return ioctl(fds[0], ANDROID_ALARM_SET(type), ts);
 }
 
+int AlarmImplAlarmDriver::setTime(struct timeval *tv)
+{
+    struct timespec ts;
+    int res;
+
+    ts.tv_sec = tv->tv_sec;
+    ts.tv_nsec = tv->tv_usec * 1000;
+    res = ioctl(fds[0], ANDROID_ALARM_SET_RTC, &ts);
+    if (res < 0)
+        ALOGV("ANDROID_ALARM_SET_RTC ioctl failed: %s\n", strerror(errno));
+    return res;
+}
+
 int AlarmImplAlarmDriver::waitForAlarm()
 {
     return ioctl(fds[0], ANDROID_ALARM_WAIT);
@@ -140,6 +157,50 @@
     return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL);
 }
 
+int AlarmImplTimerFd::setTime(struct timeval *tv)
+{
+    struct rtc_time rtc;
+    struct tm tm, *gmtime_res;
+    int fd;
+    int res;
+
+    res = settimeofday(tv, NULL);
+    if (res < 0) {
+        ALOGV("settimeofday() failed: %s\n", strerror(errno));
+        return -1;
+    }
+
+    fd = open("/dev/rtc0", O_RDWR);
+    if (fd < 0) {
+        ALOGV("Unable to open RTC driver: %s\n", strerror(errno));
+        return res;
+    }
+
+    gmtime_res = gmtime_r(&tv->tv_sec, &tm);
+    if (!gmtime_res) {
+        ALOGV("gmtime_r() failed: %s\n", strerror(errno));
+        res = -1;
+        goto done;
+    }
+
+    memset(&rtc, 0, sizeof(rtc));
+    rtc.tm_sec = tm.tm_sec;
+    rtc.tm_min = tm.tm_min;
+    rtc.tm_hour = tm.tm_hour;
+    rtc.tm_mday = tm.tm_mday;
+    rtc.tm_mon = tm.tm_mon;
+    rtc.tm_year = tm.tm_year;
+    rtc.tm_wday = tm.tm_wday;
+    rtc.tm_yday = tm.tm_yday;
+    rtc.tm_isdst = tm.tm_isdst;
+    res = ioctl(fd, RTC_SET_TIME, &rtc);
+    if (res < 0)
+        ALOGV("RTC_SET_TIME ioctl failed: %s\n", strerror(errno));
+done:
+    close(fd);
+    return res;
+}
+
 int AlarmImplTimerFd::waitForAlarm()
 {
     epoll_event events[N_ANDROID_TIMERFDS];
@@ -168,6 +229,30 @@
     return result;
 }
 
+static jint android_server_AlarmManagerService_setKernelTime(JNIEnv*, jobject, jlong nativeData, jlong millis)
+{
+    AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
+    struct timeval tv;
+    int ret;
+
+    if (millis <= 0 || millis / 1000LL >= INT_MAX) {
+        return -1;
+    }
+
+    tv.tv_sec = (time_t) (millis / 1000LL);
+    tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL);
+
+    ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec);
+
+    ret = impl->setTime(&tv);
+
+    if(ret < 0) {
+        ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno));
+        ret = -1;
+    }
+    return ret;
+}
+
 static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv*, jobject, jlong, jint minswest)
 {
     struct timezone tz;
@@ -309,6 +394,7 @@
     {"close", "(J)V", (void*)android_server_AlarmManagerService_close},
     {"set", "(JIJJ)V", (void*)android_server_AlarmManagerService_set},
     {"waitForAlarm", "(J)I", (void*)android_server_AlarmManagerService_waitForAlarm},
+    {"setKernelTime", "(JJ)I", (void*)android_server_AlarmManagerService_setKernelTime},
     {"setKernelTimezone", "(JI)I", (void*)android_server_AlarmManagerService_setKernelTimezone},
 };
 
diff --git a/services/jni/com_android_server_AssetAtlasService.cpp b/services/jni/com_android_server_AssetAtlasService.cpp
index 4a1b55d..163692b 100644
--- a/services/jni/com_android_server_AssetAtlasService.cpp
+++ b/services/jni/com_android_server_AssetAtlasService.cpp
@@ -73,7 +73,7 @@
     SkSafeUnref(previousCanvas);
 }
 
-static SkBitmap* com_android_server_AssetAtlasService_acquireCanvas(JNIEnv* env, jobject,
+static jlong com_android_server_AssetAtlasService_acquireCanvas(JNIEnv* env, jobject,
         jobject canvas, jint width, jint height) {
 
     SkBitmap* bitmap = new SkBitmap;
@@ -84,12 +84,13 @@
     SkCanvas* nativeCanvas = SkNEW_ARGS(SkCanvas, (*bitmap));
     swapCanvasPtr(env, canvas, nativeCanvas);
 
-    return bitmap;
+    return reinterpret_cast<jlong>(bitmap);
 }
 
 static void com_android_server_AssetAtlasService_releaseCanvas(JNIEnv* env, jobject,
-        jobject canvas, SkBitmap* bitmap) {
+        jobject canvas, jlong bitmapHandle) {
 
+    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
     SkCanvas* nativeCanvas = SkNEW(SkCanvas);
     swapCanvasPtr(env, canvas, nativeCanvas);
 
@@ -108,21 +109,22 @@
     return result;
 
 static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject,
-        jobject graphicBuffer, SkBitmap* bitmap) {
+        jobject graphicBuffer, jlong bitmapHandle) {
 
+    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
     // The goal of this method is to copy the bitmap into the GraphicBuffer
     // using the GPU to swizzle the texture content
     sp<GraphicBuffer> buffer(graphicBufferForJavaObject(env, graphicBuffer));
 
     if (buffer != NULL) {
         EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-        if (display == EGL_NO_DISPLAY) return false;
+        if (display == EGL_NO_DISPLAY) return JNI_FALSE;
 
         EGLint major;
         EGLint minor;
         if (!eglInitialize(display, &major, &minor)) {
             ALOGW("Could not initialize EGL");
-            return false;
+            return JNI_FALSE;
         }
 
         // We're going to use a 1x1 pbuffer surface later on
@@ -143,13 +145,13 @@
             ALOGW("Could not select EGL configuration");
             eglReleaseThread();
             eglTerminate(display);
-            return false;
+            return JNI_FALSE;
         }
         if (configCount <= 0) {
             ALOGW("Could not find EGL configuration");
             eglReleaseThread();
             eglTerminate(display);
-            return false;
+            return JNI_FALSE;
         }
 
         // These objects are initialized below but the default "null"
@@ -164,7 +166,7 @@
         EGLContext context = eglCreateContext(display, configs[0], EGL_NO_CONTEXT, attrs);
         if (context == EGL_NO_CONTEXT) {
             ALOGW("Could not create EGL context");
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
         // Create the 1x1 pbuffer
@@ -172,12 +174,12 @@
         surface = eglCreatePbufferSurface(display, configs[0], surfaceAttrs);
         if (surface == EGL_NO_SURFACE) {
             ALOGW("Could not create EGL surface");
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
         if (!eglMakeCurrent(display, surface, surface, context)) {
             ALOGW("Could not change current EGL context");
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
         // We use an EGLImage to access the content of the GraphicBuffer
@@ -188,7 +190,7 @@
                 EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttrs);
         if (image == EGL_NO_IMAGE_KHR) {
             ALOGW("Could not create EGL image");
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
         glGenTextures(1, &texture);
@@ -196,7 +198,7 @@
         glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
         if (glGetError() != GL_NO_ERROR) {
             ALOGW("Could not create/bind texture");
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
         // Upload the content of the bitmap in the GraphicBuffer
@@ -205,7 +207,7 @@
                 GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels());
         if (glGetError() != GL_NO_ERROR) {
             ALOGW("Could not upload to texture");
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
         // The fence is used to wait for the texture upload to finish
@@ -214,7 +216,7 @@
         fence = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, NULL);
         if (fence == EGL_NO_SYNC_KHR) {
             ALOGW("Could not create sync fence %#x", eglGetError());
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
         // The flag EGL_SYNC_FLUSH_COMMANDS_BIT_KHR will trigger a
@@ -223,13 +225,13 @@
                 EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, FENCE_TIMEOUT);
         if (waitStatus != EGL_CONDITION_SATISFIED_KHR) {
             ALOGW("Failed to wait for the fence %#x", eglGetError());
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
-        CLEANUP_GL_AND_RETURN(true);
+        CLEANUP_GL_AND_RETURN(JNI_TRUE);
     }
 
-    return false;
+    return JNI_FALSE;
 }
 
 // ----------------------------------------------------------------------------
@@ -247,11 +249,11 @@
 const char* const kClassPathName = "com/android/server/AssetAtlasService";
 
 static JNINativeMethod gMethods[] = {
-    { "nAcquireAtlasCanvas", "(Landroid/graphics/Canvas;II)I",
+    { "nAcquireAtlasCanvas", "(Landroid/graphics/Canvas;II)J",
             (void*) com_android_server_AssetAtlasService_acquireCanvas },
-    { "nReleaseAtlasCanvas", "(Landroid/graphics/Canvas;I)V",
+    { "nReleaseAtlasCanvas", "(Landroid/graphics/Canvas;J)V",
             (void*) com_android_server_AssetAtlasService_releaseCanvas },
-    { "nUploadAtlas", "(Landroid/view/GraphicBuffer;I)Z",
+    { "nUploadAtlas", "(Landroid/view/GraphicBuffer;J)Z",
             (void*) com_android_server_AssetAtlasService_upload },
 };
 
diff --git a/services/jni/com_android_server_UsbHostManager.cpp b/services/jni/com_android_server_UsbHostManager.cpp
index f1fa6cf..fc6de60 100644
--- a/services/jni/com_android_server_UsbHostManager.cpp
+++ b/services/jni/com_android_server_UsbHostManager.cpp
@@ -163,8 +163,10 @@
         return NULL;
 
     int fd = usb_device_get_fd(device);
-    if (fd < 0)
+    if (fd < 0) {
+        usb_device_close(device);
         return NULL;
+    }
     int newFD = dup(fd);
     usb_device_close(device);
 
diff --git a/tests/SmokeTest/tests/AndroidManifest.xml b/tests/SmokeTest/tests/AndroidManifest.xml
index cad37c5..f1a0a4c 100644
--- a/tests/SmokeTest/tests/AndroidManifest.xml
+++ b/tests/SmokeTest/tests/AndroidManifest.xml
@@ -27,15 +27,6 @@
     </application>
 
     <!--
-    This declares that this app uses the instrumentation test runner targeting the package of
-    com.android.smoketest.  To run the tests use the command:
-    `adb shell am instrument -w com.android.smoketest.tests/android.test.InstrumentationTestRunner`
-    -->
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
-                     android:targetPackage="com.android.smoketest"
-                     android:label="System Smoke Tests"/>
-
-    <!--
     This declares a method to run the instrumentation with a special runner, which will run each
     app as a separate testcase.  To do so, use the command:
     `adb shell am instrument -w com.android.smoketest.tests/com.android.smoketest.SmokeTestRunner`
diff --git a/tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java b/tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java
index 03c2923..946299b 100644
--- a/tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java
+++ b/tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java
@@ -154,6 +154,11 @@
 
         // launch app, and wait 7 seconds for it to start/settle
         final Intent intent = intentForActivity(app);
+        if (intent == null) {
+            Log.i(TAG, String.format("Activity %s/%s is disabled, skipping",
+                    app.activityInfo.packageName, app.activityInfo.name));
+            return Collections.EMPTY_LIST;
+        }
         getContext().startActivity(intent);
         try {
             Thread.sleep(appLaunchWait);
@@ -238,10 +243,16 @@
     /**
      * A helper function to create an {@link Intent} to run, given a {@link ResolveInfo} specifying
      * an activity to be launched.
+     * 
+     * @return the {@link Intent} or <code>null</code> if given app is disabled
      */
-    static Intent intentForActivity(ResolveInfo app) {
+    Intent intentForActivity(ResolveInfo app) {
         final ComponentName component = new ComponentName(app.activityInfo.packageName,
                 app.activityInfo.name);
+        if (getContext().getPackageManager().getComponentEnabledSetting(component) == 
+                PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
+            return null;
+        }
         final Intent intent = new Intent(Intent.ACTION_MAIN);
         intent.setComponent(component);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index ebf4538..19532e8 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -149,205 +149,506 @@
 // =========================================================================
 // =========================================================================
 
-status_t
-AaptGroupEntry::parseNamePart(const String8& part, int* axis, uint32_t* value)
+/* static */ void AaptLocaleValue::splitAndLowerCase(const char* const chars,
+        Vector<String8>* parts, const char separator) {
+    const char *p = chars;
+    const char *q;
+    while (NULL != (q = strchr(p, separator))) {
+         String8 val(p, q - p);
+         val.toLower();
+         parts->add(val);
+         p = q+1;
+    }
+
+    if (p < chars + strlen(chars)) {
+        String8 val(p);
+        val.toLower();
+        parts->add(val);
+    }
+}
+
+/* static */
+inline bool isAlpha(const String8& string) {
+     const size_t length = string.length();
+     for (size_t i = 0; i < length; ++i) {
+          if (!isalpha(string[i])) {
+              return false;
+          }
+     }
+
+     return true;
+}
+
+/* static */
+inline bool isNumber(const String8& string) {
+     const size_t length = string.length();
+     for (size_t i = 0; i < length; ++i) {
+          if (!isdigit(string[i])) {
+              return false;
+          }
+     }
+
+     return true;
+}
+
+void AaptLocaleValue::setLanguage(const char* languageChars) {
+     size_t i = 0;
+     while ((*languageChars) != '\0') {
+          language[i++] = tolower(*languageChars);
+          languageChars++;
+     }
+}
+
+void AaptLocaleValue::setRegion(const char* regionChars) {
+    size_t i = 0;
+    while ((*regionChars) != '\0') {
+         region[i++] = toupper(*regionChars);
+         regionChars++;
+    }
+}
+
+void AaptLocaleValue::setScript(const char* scriptChars) {
+    size_t i = 0;
+    while ((*scriptChars) != '\0') {
+         if (i == 0) {
+             script[i++] = toupper(*scriptChars);
+         } else {
+             script[i++] = tolower(*scriptChars);
+         }
+         scriptChars++;
+    }
+}
+
+void AaptLocaleValue::setVariant(const char* variantChars) {
+     size_t i = 0;
+     while ((*variantChars) != '\0') {
+          variant[i++] = *variantChars;
+          variantChars++;
+     }
+}
+
+bool AaptLocaleValue::initFromFilterString(const String8& str) {
+     // A locale (as specified in the filter) is an underscore separated name such
+     // as "en_US", "en_Latn_US", or "en_US_POSIX".
+     Vector<String8> parts;
+     splitAndLowerCase(str.string(), &parts, '_');
+
+     const int numTags = parts.size();
+     bool valid = false;
+     if (numTags >= 1) {
+         const String8& lang = parts[0];
+         if (isAlpha(lang) && (lang.length() == 2 || lang.length() == 3)) {
+             setLanguage(lang.string());
+             valid = true;
+         }
+     }
+
+     if (!valid || numTags == 1) {
+         return valid;
+     }
+
+     // At this point, valid == true && numTags > 1.
+     const String8& part2 = parts[1];
+     if ((part2.length() == 2 && isAlpha(part2)) ||
+         (part2.length() == 3 && isNumber(part2))) {
+         setRegion(part2.string());
+     } else if (part2.length() == 4 && isAlpha(part2)) {
+         setScript(part2.string());
+     } else if (part2.length() >= 5 && part2.length() <= 8) {
+         setVariant(part2.string());
+     } else {
+         valid = false;
+     }
+
+     if (!valid || numTags == 2) {
+         return valid;
+     }
+
+     // At this point, valid == true && numTags > 1.
+     const String8& part3 = parts[2];
+     if (((part3.length() == 2 && isAlpha(part3)) ||
+         (part3.length() == 3 && isNumber(part3))) && script[0]) {
+         setRegion(part3.string());
+     } else if (part3.length() >= 5 && part3.length() <= 8) {
+         setVariant(part3.string());
+     } else {
+         valid = false;
+     }
+
+     if (!valid || numTags == 3) {
+         return valid;
+     }
+
+     const String8& part4 = parts[3];
+     if (part4.length() >= 5 && part4.length() <= 8) {
+         setVariant(part4.string());
+     } else {
+         valid = false;
+     }
+
+     if (!valid || numTags > 4) {
+         return false;
+     }
+
+     return true;
+}
+
+int AaptLocaleValue::initFromDirName(const Vector<String8>& parts, const int startIndex) {
+    const int size = parts.size();
+    int currentIndex = startIndex;
+
+    String8 part = parts[currentIndex];
+    if (part[0] == 'b' && part[1] == '+') {
+        // This is a "modified" BCP-47 language tag. Same semantics as BCP-47 tags,
+        // except that the separator is "+" and not "-".
+        Vector<String8> subtags;
+        AaptLocaleValue::splitAndLowerCase(part.string(), &subtags, '+');
+        subtags.removeItemsAt(0);
+        if (subtags.size() == 1) {
+            setLanguage(subtags[0]);
+        } else if (subtags.size() == 2) {
+            setLanguage(subtags[0]);
+
+            // The second tag can either be a region, a variant or a script.
+            switch (subtags[1].size()) {
+                case 2:
+                case 3:
+                    setRegion(subtags[1]);
+                    break;
+                case 4:
+                    setScript(subtags[1]);
+                    break;
+                case 5:
+                case 6:
+                case 7:
+                case 8:
+                    setVariant(subtags[1]);
+                    break;
+                default:
+                    fprintf(stderr, "ERROR: Invalid BCP-47 tag in directory name %s\n",
+                            part.string());
+                    return -1;
+            }
+        } else if (subtags.size() == 3) {
+            // The language is always the first subtag.
+            setLanguage(subtags[0]);
+
+            // The second subtag can either be a script or a region code.
+            // If its size is 4, it's a script code, else it's a region code.
+            bool hasRegion = false;
+            if (subtags[1].size() == 4) {
+                setScript(subtags[1]);
+            } else if (subtags[1].size() == 2 || subtags[1].size() == 3) {
+                setRegion(subtags[1]);
+                hasRegion = true;
+            } else {
+                fprintf(stderr, "ERROR: Invalid BCP-47 tag in directory name %s\n", part.string());
+                return -1;
+            }
+
+            // The third tag can either be a region code (if the second tag was
+            // a script), else a variant code.
+            if (subtags[2].size() > 4) {
+                setVariant(subtags[2]);
+            } else {
+                setRegion(subtags[2]);
+            }
+        } else if (subtags.size() == 4) {
+            setLanguage(subtags[0]);
+            setScript(subtags[1]);
+            setRegion(subtags[2]);
+            setVariant(subtags[3]);
+        } else {
+            fprintf(stderr, "ERROR: Invalid BCP-47 tag in directory name: %s\n", part.string());
+            return -1;
+        }
+
+        return ++currentIndex;
+    } else {
+        if ((part.length() == 2 || part.length() == 3) && isAlpha(part)) {
+            setLanguage(part);
+            if (++currentIndex == size) {
+                return size;
+            }
+        } else {
+            return currentIndex;
+        }
+
+        part = parts[currentIndex];
+        if (part.string()[0] == 'r' && part.length() == 3) {
+            setRegion(part.string() + 1);
+            if (++currentIndex == size) {
+                return size;
+            }
+        }
+    }
+
+    return currentIndex;
+}
+
+
+String8 AaptLocaleValue::toDirName() const {
+    String8 dirName("");
+    if (language[0]) {
+        dirName += language;
+    } else {
+        return dirName;
+    }
+
+    if (script[0]) {
+        dirName += "-s";
+        dirName += script;
+    }
+
+    if (region[0]) {
+        dirName += "-r";
+        dirName += region;
+    }
+
+    if (variant[0]) {
+        dirName += "-v";
+        dirName += variant;
+    }
+
+    return dirName;
+}
+
+void AaptLocaleValue::initFromResTable(const ResTable_config& config) {
+    config.unpackLanguage(language);
+    config.unpackRegion(region);
+    if (config.localeScript[0]) {
+        memcpy(script, config.localeScript, sizeof(config.localeScript));
+    }
+
+    if (config.localeVariant[0]) {
+        memcpy(variant, config.localeVariant, sizeof(config.localeVariant));
+    }
+}
+
+void AaptLocaleValue::writeTo(ResTable_config* out) const {
+    out->packLanguage(language);
+    out->packRegion(region);
+
+    if (script[0]) {
+        memcpy(out->localeScript, script, sizeof(out->localeScript));
+    }
+
+    if (variant[0]) {
+        memcpy(out->localeVariant, variant, sizeof(out->localeVariant));
+    }
+}
+
+
+/* static */ bool
+AaptGroupEntry::parseFilterNamePart(const String8& part, int* axis, AxisValue* value)
 {
     ResTable_config config;
+    memset(&config, 0, sizeof(ResTable_config));
 
     // IMSI - MCC
     if (getMccName(part.string(), &config)) {
         *axis = AXIS_MCC;
-        *value = config.mcc;
-        return 0;
+        value->intValue = config.mcc;
+        return true;
     }
 
     // IMSI - MNC
     if (getMncName(part.string(), &config)) {
         *axis = AXIS_MNC;
-        *value = config.mnc;
-        return 0;
+        value->intValue = config.mnc;
+        return true;
     }
 
     // locale - language
-    if (part.length() == 2 && isalpha(part[0]) && isalpha(part[1])) {
-        *axis = AXIS_LANGUAGE;
-        *value = part[1] << 8 | part[0];
-        return 0;
-    }
-
-    // locale - language_REGION
-    if (part.length() == 5 && isalpha(part[0]) && isalpha(part[1])
-            && part[2] == '_' && isalpha(part[3]) && isalpha(part[4])) {
-        *axis = AXIS_LANGUAGE;
-        *value = (part[4] << 24) | (part[3] << 16) | (part[1] << 8) | (part[0]);
-        return 0;
+    if (value->localeValue.initFromFilterString(part)) {
+        *axis = AXIS_LOCALE;
+        return true;
     }
 
     // layout direction
     if (getLayoutDirectionName(part.string(), &config)) {
         *axis = AXIS_LAYOUTDIR;
-        *value = (config.screenLayout&ResTable_config::MASK_LAYOUTDIR);
-        return 0;
+        value->intValue = (config.screenLayout&ResTable_config::MASK_LAYOUTDIR);
+        return true;
     }
 
     // smallest screen dp width
     if (getSmallestScreenWidthDpName(part.string(), &config)) {
         *axis = AXIS_SMALLESTSCREENWIDTHDP;
-        *value = config.smallestScreenWidthDp;
-        return 0;
+        value->intValue = config.smallestScreenWidthDp;
+        return true;
     }
 
     // screen dp width
     if (getScreenWidthDpName(part.string(), &config)) {
         *axis = AXIS_SCREENWIDTHDP;
-        *value = config.screenWidthDp;
-        return 0;
+        value->intValue = config.screenWidthDp;
+        return true;
     }
 
     // screen dp height
     if (getScreenHeightDpName(part.string(), &config)) {
         *axis = AXIS_SCREENHEIGHTDP;
-        *value = config.screenHeightDp;
-        return 0;
+        value->intValue = config.screenHeightDp;
+        return true;
     }
 
     // screen layout size
     if (getScreenLayoutSizeName(part.string(), &config)) {
         *axis = AXIS_SCREENLAYOUTSIZE;
-        *value = (config.screenLayout&ResTable_config::MASK_SCREENSIZE);
-        return 0;
+        value->intValue = (config.screenLayout&ResTable_config::MASK_SCREENSIZE);
+        return true;
     }
 
     // screen layout long
     if (getScreenLayoutLongName(part.string(), &config)) {
         *axis = AXIS_SCREENLAYOUTLONG;
-        *value = (config.screenLayout&ResTable_config::MASK_SCREENLONG);
-        return 0;
+        value->intValue = (config.screenLayout&ResTable_config::MASK_SCREENLONG);
+        return true;
     }
 
     // orientation
     if (getOrientationName(part.string(), &config)) {
         *axis = AXIS_ORIENTATION;
-        *value = config.orientation;
-        return 0;
+        value->intValue = config.orientation;
+        return true;
     }
 
     // ui mode type
     if (getUiModeTypeName(part.string(), &config)) {
         *axis = AXIS_UIMODETYPE;
-        *value = (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
-        return 0;
+        value->intValue = (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
+        return true;
     }
 
     // ui mode night
     if (getUiModeNightName(part.string(), &config)) {
         *axis = AXIS_UIMODENIGHT;
-        *value = (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
-        return 0;
+        value->intValue = (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
+        return true;
     }
 
     // density
     if (getDensityName(part.string(), &config)) {
         *axis = AXIS_DENSITY;
-        *value = config.density;
-        return 0;
+        value->intValue = config.density;
+        return true;
     }
 
     // touchscreen
     if (getTouchscreenName(part.string(), &config)) {
         *axis = AXIS_TOUCHSCREEN;
-        *value = config.touchscreen;
-        return 0;
+        value->intValue = config.touchscreen;
+        return true;
     }
 
     // keyboard hidden
     if (getKeysHiddenName(part.string(), &config)) {
         *axis = AXIS_KEYSHIDDEN;
-        *value = config.inputFlags;
-        return 0;
+        value->intValue = config.inputFlags;
+        return true;
     }
 
     // keyboard
     if (getKeyboardName(part.string(), &config)) {
         *axis = AXIS_KEYBOARD;
-        *value = config.keyboard;
-        return 0;
+        value->intValue = config.keyboard;
+        return true;
     }
 
     // navigation hidden
     if (getNavHiddenName(part.string(), &config)) {
         *axis = AXIS_NAVHIDDEN;
-        *value = config.inputFlags;
+        value->intValue = config.inputFlags;
         return 0;
     }
 
     // navigation
     if (getNavigationName(part.string(), &config)) {
         *axis = AXIS_NAVIGATION;
-        *value = config.navigation;
-        return 0;
+        value->intValue = config.navigation;
+        return true;
     }
 
     // screen size
     if (getScreenSizeName(part.string(), &config)) {
         *axis = AXIS_SCREENSIZE;
-        *value = config.screenSize;
-        return 0;
+        value->intValue = config.screenSize;
+        return true;
     }
 
     // version
     if (getVersionName(part.string(), &config)) {
         *axis = AXIS_VERSION;
-        *value = config.version;
-        return 0;
+        value->intValue = config.version;
+        return true;
     }
 
-    return 1;
+    return false;
 }
 
-uint32_t
+AxisValue
 AaptGroupEntry::getConfigValueForAxis(const ResTable_config& config, int axis)
 {
+    AxisValue value;
     switch (axis) {
         case AXIS_MCC:
-            return config.mcc;
+            value.intValue = config.mcc;
+            break;
         case AXIS_MNC:
-            return config.mnc;
-        case AXIS_LANGUAGE:
-            return (((uint32_t)config.country[1]) << 24) | (((uint32_t)config.country[0]) << 16)
-                | (((uint32_t)config.language[1]) << 8) | (config.language[0]);
+            value.intValue = config.mnc;
+            break;
+        case AXIS_LOCALE:
+            value.localeValue.initFromResTable(config);
+            break;
         case AXIS_LAYOUTDIR:
-            return config.screenLayout&ResTable_config::MASK_LAYOUTDIR;
+            value.intValue = config.screenLayout&ResTable_config::MASK_LAYOUTDIR;
+            break;
         case AXIS_SCREENLAYOUTSIZE:
-            return config.screenLayout&ResTable_config::MASK_SCREENSIZE;
+            value.intValue = config.screenLayout&ResTable_config::MASK_SCREENSIZE;
+            break;
         case AXIS_ORIENTATION:
-            return config.orientation;
+            value.intValue = config.orientation;
+            break;
         case AXIS_UIMODETYPE:
-            return (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
+            value.intValue = (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
+            break;
         case AXIS_UIMODENIGHT:
-            return (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
+            value.intValue = (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
+            break;
         case AXIS_DENSITY:
-            return config.density;
+            value.intValue = config.density;
+            break;
         case AXIS_TOUCHSCREEN:
-            return config.touchscreen;
+            value.intValue = config.touchscreen;
+            break;
         case AXIS_KEYSHIDDEN:
-            return config.inputFlags;
+            value.intValue = config.inputFlags;
+            break;
         case AXIS_KEYBOARD:
-            return config.keyboard;
+            value.intValue = config.keyboard;
+            break;
         case AXIS_NAVIGATION:
-            return config.navigation;
+            value.intValue = config.navigation;
+            break;
         case AXIS_SCREENSIZE:
-            return config.screenSize;
+            value.intValue = config.screenSize;
+            break;
         case AXIS_SMALLESTSCREENWIDTHDP:
-            return config.smallestScreenWidthDp;
+            value.intValue = config.smallestScreenWidthDp;
+            break;
         case AXIS_SCREENWIDTHDP:
-            return config.screenWidthDp;
+            value.intValue = config.screenWidthDp;
+            break;
         case AXIS_SCREENHEIGHTDP:
-            return config.screenHeightDp;
+            value.intValue = config.screenHeightDp;
+            break;
         case AXIS_VERSION:
-            return config.version;
+            value.intValue = config.version;
+            break;
     }
-    return 0;
+
+    return value;
 }
 
 bool
@@ -371,24 +672,14 @@
     mParamsChanged = true;
 
     Vector<String8> parts;
+    AaptLocaleValue::splitAndLowerCase(dir, &parts, '-');
 
-    String8 mcc, mnc, loc, layoutsize, layoutlong, orient, den;
+    String8 mcc, mnc, layoutsize, layoutlong, orient, den;
     String8 touch, key, keysHidden, nav, navHidden, size, layoutDir, vers;
     String8 uiModeType, uiModeNight, smallestwidthdp, widthdp, heightdp;
 
-    const char *p = dir;
-    const char *q;
-    while (NULL != (q = strchr(p, '-'))) {
-        String8 val(p, q-p);
-        val.toLower();
-        parts.add(val);
-        //printf("part: %s\n", parts[parts.size()-1].string());
-        p = q+1;
-    }
-    String8 val(p);
-    val.toLower();
-    parts.add(val);
-    //printf("part: %s\n", parts[parts.size()-1].string());
+    AaptLocaleValue locale;
+    int numLocaleComponents = 0;
 
     const int N = parts.size();
     int index = 0;
@@ -429,38 +720,18 @@
         }
         part = parts[index];
     } else {
-        //printf("not mcc: %s\n", part.string());
+        //printf("not mnc: %s\n", part.string());
     }
 
-    // locale - language
-    if (part.length() == 2 && isalpha(part[0]) && isalpha(part[1])) {
-        loc = part;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not language: %s\n", part.string());
+    index = locale.initFromDirName(parts, index);
+    if (index == -1) {
+        return false;
+    }
+    if (index >= N){
+        goto success;
     }
 
-    // locale - region
-    if (loc.length() > 0
-            && part.length() == 3 && part[0] == 'r' && part[0] && part[1]) {
-        loc += "-";
-        part.toUpper();
-        loc += part.string() + 1;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not region: %s\n", part.string());
-    }
-
+    part = parts[index];
     if (getLayoutDirectionName(part.string())) {
         layoutDir = part;
 
@@ -679,7 +950,7 @@
 success:
     this->mcc = mcc;
     this->mnc = mnc;
-    this->locale = loc;
+    this->locale = locale;
     this->screenLayoutSize = layoutsize;
     this->screenLayoutLong = layoutlong;
     this->smallestScreenWidthDp = smallestwidthdp;
@@ -711,7 +982,7 @@
     s += ",";
     s += this->mnc;
     s += ",";
-    s += this->locale;
+    s += locale.toDirName();
     s += ",";
     s += layoutDirection;
     s += ",";
@@ -765,12 +1036,15 @@
         }
         s += mnc;
     }
-    if (this->locale != "") {
-        if (s.length() > 0) {
-            s += "-";
-        }
-        s += locale;
+
+    const String8 localeComponent = locale.toDirName();
+    if (localeComponent != "") {
+         if (s.length() > 0) {
+             s += "-";
+         }
+         s += localeComponent;
     }
+
     if (this->layoutDirection != "") {
         if (s.length() > 0) {
             s += "-";
@@ -942,55 +1216,6 @@
     return true;
 }
 
-/*
- * Does this directory name fit the pattern of a locale dir ("en-rUS" or
- * "default")?
- *
- * TODO: Should insist that the first two letters are lower case, and the
- * second two are upper.
- */
-bool AaptGroupEntry::getLocaleName(const char* fileName,
-                                   ResTable_config* out)
-{
-    if (strcmp(fileName, kWildcardName) == 0
-            || strcmp(fileName, kDefaultLocale) == 0) {
-        if (out) {
-            out->language[0] = 0;
-            out->language[1] = 0;
-            out->country[0] = 0;
-            out->country[1] = 0;
-        }
-        return true;
-    }
-
-    if (strlen(fileName) == 2 && isalpha(fileName[0]) && isalpha(fileName[1])) {
-        if (out) {
-            out->language[0] = fileName[0];
-            out->language[1] = fileName[1];
-            out->country[0] = 0;
-            out->country[1] = 0;
-        }
-        return true;
-    }
-
-    if (strlen(fileName) == 5 &&
-        isalpha(fileName[0]) &&
-        isalpha(fileName[1]) &&
-        fileName[2] == '-' &&
-        isalpha(fileName[3]) &&
-        isalpha(fileName[4])) {
-        if (out) {
-            out->language[0] = fileName[0];
-            out->language[1] = fileName[1];
-            out->country[0] = fileName[3];
-            out->country[1] = fileName[4];
-        }
-        return true;
-    }
-
-    return false;
-}
-
 bool AaptGroupEntry::getLayoutDirectionName(const char* name, ResTable_config* out)
 {
     if (strcmp(name, kWildcardName) == 0) {
@@ -1496,18 +1721,18 @@
     return v;
 }
 
-const ResTable_config& AaptGroupEntry::toParams() const
+const ResTable_config AaptGroupEntry::toParams() const
 {
     if (!mParamsChanged) {
         return mParams;
     }
 
     mParamsChanged = false;
-    ResTable_config& params(mParams);
-    memset(&params, 0, sizeof(params));
+    ResTable_config& params = mParams;
+    memset(&params, 0, sizeof(ResTable_config));
     getMccName(mcc.string(), &params);
     getMncName(mnc.string(), &params);
-    getLocaleName(locale.string(), &params);
+    locale.writeTo(&params);
     getLayoutDirectionName(layoutDirection.string(), &params);
     getSmallestScreenWidthDpName(smallestScreenWidthDp.string(), &params);
     getScreenWidthDpName(screenWidthDp.string(), &params);
@@ -1982,7 +2207,9 @@
 
 AaptAssets::AaptAssets()
     : AaptDir(String8(), String8()),
-      mChanged(false), mHaveIncludedAssets(false), mRes(NULL)
+      mHavePrivateSymbols(false),
+      mChanged(false), mHaveIncludedAssets(false),
+      mRes(NULL)
 {
 }
 
@@ -2491,9 +2718,9 @@
             // If our preferred density is hdpi but we only have mdpi and xhdpi resources, we
             // pick xhdpi.
             uint32_t preferredDensity = 0;
-            const SortedVector<uint32_t>* preferredConfigs = prefFilter.configsForAxis(AXIS_DENSITY);
+            const SortedVector<AxisValue>* preferredConfigs = prefFilter.configsForAxis(AXIS_DENSITY);
             if (preferredConfigs != NULL && preferredConfigs->size() > 0) {
-                preferredDensity = (*preferredConfigs)[0];
+                preferredDensity = (*preferredConfigs)[0].intValue;
             }
 
             // Now deal with preferred configurations.
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index 5cfa913..9733b6d 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -13,7 +13,6 @@
 #include <utils/RefBase.h>
 #include <utils/SortedVector.h>
 #include <utils/String8.h>
-#include <utils/String8.h>
 #include <utils/Vector.h>
 #include "ZipFile.h"
 
@@ -34,8 +33,7 @@
     AXIS_NONE = 0,
     AXIS_MCC = 1,
     AXIS_MNC,
-    AXIS_LANGUAGE,
-    AXIS_REGION,
+    AXIS_LOCALE,
     AXIS_SCREENLAYOUTSIZE,
     AXIS_SCREENLAYOUTLONG,
     AXIS_ORIENTATION,
@@ -58,6 +56,73 @@
     AXIS_END = AXIS_VERSION,
 };
 
+struct AaptLocaleValue {
+     char language[4];
+     char region[4];
+     char script[4];
+     char variant[8];
+
+     AaptLocaleValue() {
+         memset(this, 0, sizeof(AaptLocaleValue));
+     }
+
+     // Initialize this AaptLocaleValue from a config string.
+     bool initFromFilterString(const String8& config);
+
+     int initFromDirName(const Vector<String8>& parts, const int startIndex);
+
+     // Initialize this AaptLocaleValue from a ResTable_config.
+     void initFromResTable(const ResTable_config& config);
+
+     void writeTo(ResTable_config* out) const;
+
+     String8 toDirName() const;
+
+     int compare(const AaptLocaleValue& other) const {
+         return memcmp(this, &other, sizeof(AaptLocaleValue));
+     }
+
+     static void splitAndLowerCase(const char* const chars, Vector<String8>* parts,
+             const char separator);
+
+     inline bool operator<(const AaptLocaleValue& o) const { return compare(o) < 0; }
+     inline bool operator<=(const AaptLocaleValue& o) const { return compare(o) <= 0; }
+     inline bool operator==(const AaptLocaleValue& o) const { return compare(o) == 0; }
+     inline bool operator!=(const AaptLocaleValue& o) const { return compare(o) != 0; }
+     inline bool operator>=(const AaptLocaleValue& o) const { return compare(o) >= 0; }
+     inline bool operator>(const AaptLocaleValue& o) const { return compare(o) > 0; }
+private:
+     void setLanguage(const char* language);
+     void setRegion(const char* language);
+     void setScript(const char* script);
+     void setVariant(const char* variant);
+};
+
+struct AxisValue {
+    // Used for all axes except AXIS_LOCALE, which is represented
+    // as a AaptLocaleValue value.
+    int intValue;
+    AaptLocaleValue localeValue;
+
+    AxisValue() : intValue(0) {
+    }
+
+    inline int compare(const AxisValue &other) const  {
+        if (intValue != other.intValue) {
+            return intValue - other.intValue;
+        }
+
+        return localeValue.compare(other.localeValue);
+    }
+
+    inline bool operator<(const AxisValue& o) const { return compare(o) < 0; }
+    inline bool operator<=(const AxisValue& o) const { return compare(o) <= 0; }
+    inline bool operator==(const AxisValue& o) const { return compare(o) == 0; }
+    inline bool operator!=(const AxisValue& o) const { return compare(o) != 0; }
+    inline bool operator>=(const AxisValue& o) const { return compare(o) >= 0; }
+    inline bool operator>(const AxisValue& o) const { return compare(o) > 0; }
+};
+
 /**
  * This structure contains a specific variation of a single file out
  * of all the variations it can have that we can have.
@@ -65,22 +130,38 @@
 struct AaptGroupEntry
 {
 public:
-    AaptGroupEntry() : mParamsChanged(true) { }
-    AaptGroupEntry(const String8& _locale, const String8& _vendor)
-        : locale(_locale), vendor(_vendor), mParamsChanged(true) { }
+    AaptGroupEntry() : mParamsChanged(true) {
+        memset(&mParams, 0, sizeof(ResTable_config));
+    }
 
     bool initFromDirName(const char* dir, String8* resType);
 
-    static status_t parseNamePart(const String8& part, int* axis, uint32_t* value);
+    static bool parseFilterNamePart(const String8& part, int* axis, AxisValue* value);
 
-    static uint32_t getConfigValueForAxis(const ResTable_config& config, int axis);
+    static AxisValue getConfigValueForAxis(const ResTable_config& config, int axis);
 
     static bool configSameExcept(const ResTable_config& config,
             const ResTable_config& otherConfig, int axis);
 
+    int compare(const AaptGroupEntry& o) const;
+
+    const ResTable_config toParams() const;
+
+    inline bool operator<(const AaptGroupEntry& o) const { return compare(o) < 0; }
+    inline bool operator<=(const AaptGroupEntry& o) const { return compare(o) <= 0; }
+    inline bool operator==(const AaptGroupEntry& o) const { return compare(o) == 0; }
+    inline bool operator!=(const AaptGroupEntry& o) const { return compare(o) != 0; }
+    inline bool operator>=(const AaptGroupEntry& o) const { return compare(o) >= 0; }
+    inline bool operator>(const AaptGroupEntry& o) const { return compare(o) > 0; }
+
+    String8 toString() const;
+    String8 toDirName(const String8& resType) const;
+
+    const String8& getVersionString() const { return version; }
+
+private:
     static bool getMccName(const char* name, ResTable_config* out = NULL);
     static bool getMncName(const char* name, ResTable_config* out = NULL);
-    static bool getLocaleName(const char* name, ResTable_config* out = NULL);
     static bool getScreenLayoutSizeName(const char* name, ResTable_config* out = NULL);
     static bool getScreenLayoutLongName(const char* name, ResTable_config* out = NULL);
     static bool getOrientationName(const char* name, ResTable_config* out = NULL);
@@ -99,26 +180,9 @@
     static bool getLayoutDirectionName(const char* name, ResTable_config* out = NULL);
     static bool getVersionName(const char* name, ResTable_config* out = NULL);
 
-    int compare(const AaptGroupEntry& o) const;
-
-    const ResTable_config& toParams() const;
-
-    inline bool operator<(const AaptGroupEntry& o) const { return compare(o) < 0; }
-    inline bool operator<=(const AaptGroupEntry& o) const { return compare(o) <= 0; }
-    inline bool operator==(const AaptGroupEntry& o) const { return compare(o) == 0; }
-    inline bool operator!=(const AaptGroupEntry& o) const { return compare(o) != 0; }
-    inline bool operator>=(const AaptGroupEntry& o) const { return compare(o) >= 0; }
-    inline bool operator>(const AaptGroupEntry& o) const { return compare(o) > 0; }
-
-    String8 toString() const;
-    String8 toDirName(const String8& resType) const;
-
-    const String8& getVersionString() const { return version; }
-
-private:
     String8 mcc;
     String8 mnc;
-    String8 locale;
+    AaptLocaleValue locale;
     String8 vendor;
     String8 smallestScreenWidthDp;
     String8 screenWidthDp;
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 8a6faed..c7cce96 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -517,6 +517,7 @@
     // the API version because key resources like icons will have an implicit
     // version if they are using newer config types like density.
     ResTable_config config;
+    memset(&config, 0, sizeof(ResTable_config));
     config.language[0] = 'e';
     config.language[1] = 'n';
     config.country[0] = 'U';
diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp
index 25a948d..db74831 100644
--- a/tools/aapt/Images.cpp
+++ b/tools/aapt/Images.cpp
@@ -35,7 +35,9 @@
 // This holds an image as 8bpp RGBA.
 struct image_info
 {
-    image_info() : rows(NULL), is9Patch(false), allocRows(NULL) { }
+    image_info() : rows(NULL), is9Patch(false),
+        xDivs(NULL), yDivs(NULL), colors(NULL), allocRows(NULL) { }
+
     ~image_info() {
         if (rows && rows != allocRows) {
             free(rows);
@@ -46,9 +48,15 @@
             }
             free(allocRows);
         }
-        free(info9Patch.xDivs);
-        free(info9Patch.yDivs);
-        free(info9Patch.colors);
+        free(xDivs);
+        free(yDivs);
+        free(colors);
+    }
+
+    void* serialize9patch() {
+        void* serialized = Res_png_9patch::serialize(info9Patch, xDivs, yDivs, colors);
+        reinterpret_cast<Res_png_9patch*>(serialized)->deviceToFile();
+        return serialized;
     }
 
     png_uint_32 width;
@@ -58,6 +66,9 @@
     // 9-patch info.
     bool is9Patch;
     Res_png_9patch info9Patch;
+    int32_t* xDivs;
+    int32_t* yDivs;
+    uint32_t* colors;
 
     // Layout padding, if relevant
     bool haveLayoutBounds;
@@ -430,10 +441,10 @@
 {
     int left, right, top, bottom;
     select_patch(
-        hpatch, image->info9Patch.xDivs[0], image->info9Patch.xDivs[1],
+        hpatch, image->xDivs[0], image->xDivs[1],
         image->width, &left, &right);
     select_patch(
-        vpatch, image->info9Patch.yDivs[0], image->info9Patch.yDivs[1],
+        vpatch, image->yDivs[0], image->yDivs[1],
         image->height, &top, &bottom);
     //printf("Selecting h=%d v=%d: (%d,%d)-(%d,%d)\n",
     //       hpatch, vpatch, left, top, right, bottom);
@@ -452,8 +463,8 @@
 
     int maxSizeXDivs = W * sizeof(int32_t);
     int maxSizeYDivs = H * sizeof(int32_t);
-    int32_t* xDivs = image->info9Patch.xDivs = (int32_t*) malloc(maxSizeXDivs);
-    int32_t* yDivs = image->info9Patch.yDivs = (int32_t*) malloc(maxSizeYDivs);
+    int32_t* xDivs = image->xDivs = (int32_t*) malloc(maxSizeXDivs);
+    int32_t* yDivs = image->yDivs = (int32_t*) malloc(maxSizeYDivs);
     uint8_t numXDivs = 0;
     uint8_t numYDivs = 0;
 
@@ -609,7 +620,7 @@
 
     numColors = numRows * numCols;
     image->info9Patch.numColors = numColors;
-    image->info9Patch.colors = (uint32_t*)malloc(numColors * sizeof(uint32_t));
+    image->colors = (uint32_t*)malloc(numColors * sizeof(uint32_t));
 
     // Fill in color information for each patch.
 
@@ -652,7 +663,7 @@
                 right = xDivs[i];
             }
             c = get_color(image->rows, left, top, right - 1, bottom - 1);
-            image->info9Patch.colors[colorIndex++] = c;
+            image->colors[colorIndex++] = c;
             NOISY(if (c != Res_png_9patch::NO_COLOR) hasColor = true);
             left = right;
         }
@@ -664,14 +675,10 @@
     for (i=0; i<numColors; i++) {
         if (hasColor) {
             if (i == 0) printf("Colors in %s:\n ", imageName);
-            printf(" #%08x", image->info9Patch.colors[i]);
+            printf(" #%08x", image->colors[i]);
             if (i == numColors - 1) printf("\n");
         }
     }
-
-    image->is9Patch = true;
-    image->info9Patch.deviceToFile();
-
 getout:
     if (errorMsg) {
         fprintf(stderr,
@@ -691,14 +698,10 @@
     return NO_ERROR;
 }
 
-static void checkNinePatchSerialization(Res_png_9patch* inPatch,  void * data)
+static void checkNinePatchSerialization(Res_png_9patch* inPatch,  void* data)
 {
-    if (sizeof(void*) != sizeof(int32_t)) {
-        // can't deserialize on a non-32 bit system
-        return;
-    }
     size_t patchSize = inPatch->serializedSize();
-    void * newData = malloc(patchSize);
+    void* newData = malloc(patchSize);
     memcpy(newData, data, patchSize);
     Res_png_9patch* outPatch = inPatch->deserialize(newData);
     // deserialization is done in place, so outPatch == newData
@@ -721,34 +724,6 @@
     free(newData);
 }
 
-static bool patch_equals(Res_png_9patch& patch1, Res_png_9patch& patch2) {
-    if (!(patch1.numXDivs == patch2.numXDivs &&
-          patch1.numYDivs == patch2.numYDivs &&
-          patch1.numColors == patch2.numColors &&
-          patch1.paddingLeft == patch2.paddingLeft &&
-          patch1.paddingRight == patch2.paddingRight &&
-          patch1.paddingTop == patch2.paddingTop &&
-          patch1.paddingBottom == patch2.paddingBottom)) {
-            return false;
-    }
-    for (int i = 0; i < patch1.numColors; i++) {
-        if (patch1.colors[i] != patch2.colors[i]) {
-            return false;
-        }
-    }
-    for (int i = 0; i < patch1.numXDivs; i++) {
-        if (patch1.xDivs[i] != patch2.xDivs[i]) {
-            return false;
-        }
-    }
-    for (int i = 0; i < patch1.numYDivs; i++) {
-        if (patch1.yDivs[i] != patch2.yDivs[i]) {
-            return false;
-        }
-    }
-    return true;
-}
-
 static void dump_image(int w, int h, png_bytepp rows, int color_type)
 {
     int i, j, rr, gg, bb, aa;
@@ -1061,7 +1036,7 @@
                 : (png_byte*)"npTc";
         NOISY(printf("Adding 9-patch info...\n"));
         strcpy((char*)unknowns[p_index].name, "npTc");
-        unknowns[p_index].data = (png_byte*)imageInfo.info9Patch.serialize();
+        unknowns[p_index].data = (png_byte*)imageInfo.serialize9patch();
         unknowns[p_index].size = imageInfo.info9Patch.serializedSize();
         // TODO: remove the check below when everything works
         checkNinePatchSerialization(&imageInfo.info9Patch, unknowns[p_index].data);
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 57d44f2..4d29ff7 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -80,6 +80,7 @@
     ResourceDirIterator(const sp<ResourceTypeSet>& set, const String8& resType)
         : mResType(resType), mSet(set), mSetPos(0), mGroupPos(0)
     {
+        memset(&mParams, 0, sizeof(ResTable_config));
     }
 
     inline const sp<AaptGroup>& getGroup() const { return mGroup; }
diff --git a/tools/aapt/ResourceFilter.cpp b/tools/aapt/ResourceFilter.cpp
index 8cfd2a5..e8a2be4 100644
--- a/tools/aapt/ResourceFilter.cpp
+++ b/tools/aapt/ResourceFilter.cpp
@@ -28,8 +28,8 @@
             mContainsPseudo = true;
         }
         int axis;
-        uint32_t value;
-        if (AaptGroupEntry::parseNamePart(part, &axis, &value)) {
+        AxisValue value;
+        if (!AaptGroupEntry::parseFilterNamePart(part, &axis, &value)) {
             fprintf(stderr, "Invalid configuration: %s\n", arg);
             fprintf(stderr, "                       ");
             for (int i=0; i<p-arg; i++) {
@@ -44,15 +44,20 @@
 
         ssize_t index = mData.indexOfKey(axis);
         if (index < 0) {
-            mData.add(axis, SortedVector<uint32_t>());
+            mData.add(axis, SortedVector<AxisValue>());
         }
-        SortedVector<uint32_t>& sv = mData.editValueFor(axis);
+        SortedVector<AxisValue>& sv = mData.editValueFor(axis);
         sv.add(value);
-        // if it's a locale with a region, also match an unmodified locale of the
-        // same language
-        if (axis == AXIS_LANGUAGE) {
-            if (value & 0xffff0000) {
-                sv.add(value & 0x0000ffff);
+
+        // If it's a locale with a region, script or variant, we should also match an
+        // unmodified locale of the same language
+        if (axis == AXIS_LOCALE) {
+            if (value.localeValue.region[0] || value.localeValue.script[0] ||
+                value.localeValue.variant[0]) {
+                AxisValue copy;
+                memcpy(copy.localeValue.language, value.localeValue.language,
+                       sizeof(value.localeValue.language));
+                sv.add(copy);
             }
         }
         p = q;
@@ -70,9 +75,9 @@
 }
 
 bool
-ResourceFilter::match(int axis, uint32_t value) const
+ResourceFilter::match(int axis, const AxisValue& value) const
 {
-    if (value == 0) {
+    if (value.intValue == 0 && (value.localeValue.language[0] == 0)) {
         // they didn't specify anything so take everything
         return true;
     }
@@ -81,7 +86,7 @@
         // we didn't request anything on this axis so take everything
         return true;
     }
-    const SortedVector<uint32_t>& sv = mData.valueAt(index);
+    const SortedVector<AxisValue>& sv = mData.valueAt(index);
     return sv.indexOf(value) >= 0;
 }
 
@@ -102,7 +107,7 @@
     return true;
 }
 
-const SortedVector<uint32_t>* ResourceFilter::configsForAxis(int axis) const
+const SortedVector<AxisValue>* ResourceFilter::configsForAxis(int axis) const
 {
     ssize_t index = mData.indexOfKey(axis);
     if (index < 0) {
diff --git a/tools/aapt/ResourceFilter.h b/tools/aapt/ResourceFilter.h
index 647b7bb..0d127ba 100644
--- a/tools/aapt/ResourceFilter.h
+++ b/tools/aapt/ResourceFilter.h
@@ -19,14 +19,15 @@
     ResourceFilter() : mData(), mContainsPseudo(false) {}
     status_t parse(const char* arg);
     bool isEmpty() const;
-    bool match(int axis, uint32_t value) const;
     bool match(int axis, const ResTable_config& config) const;
     bool match(const ResTable_config& config) const;
-    const SortedVector<uint32_t>* configsForAxis(int axis) const;
+    const SortedVector<AxisValue>* configsForAxis(int axis) const;
     inline bool containsPseudo() const { return mContainsPseudo; }
 
 private:
-    KeyedVector<int,SortedVector<uint32_t> > mData;
+    bool match(int axis, const AxisValue& value) const;
+
+    KeyedVector<int,SortedVector<AxisValue> > mData;
     bool mContainsPseudo;
 };
 
diff --git a/tools/aapt/ResourceIdCache.h b/tools/aapt/ResourceIdCache.h
index 65f7781..e6bcda2 100644
--- a/tools/aapt/ResourceIdCache.h
+++ b/tools/aapt/ResourceIdCache.h
@@ -7,7 +7,6 @@
 #define RESOURCE_ID_CACHE_H
 
 namespace android {
-class android::String16;
 
 class ResourceIdCache {
 public:
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 6ced8b3..38bf540 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -1292,8 +1292,8 @@
                 curIsStyled = true;
             } else if (strcmp16(block.getElementName(&len), string16.string()) == 0) {
                 // Note the existence and locale of every string we process
-                char rawLocale[16];
-                curParams.getLocale(rawLocale);
+                char rawLocale[RESTABLE_MAX_LOCALE_LEN];
+                curParams.getBcp47Locale(rawLocale);
                 String8 locale(rawLocale);
                 String16 name;
                 String16 translatable;
diff --git a/tools/aidl/Type.cpp b/tools/aidl/Type.cpp
index d572af6..2267750 100644
--- a/tools/aidl/Type.cpp
+++ b/tools/aidl/Type.cpp
@@ -1,5 +1,7 @@
 #include "Type.h"
 
+#include <sys/types.h>
+
 Namespace NAMES;
 
 Type* VOID_TYPE;
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
index f5c4677..06673c1 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
@@ -44,62 +44,13 @@
  */
 /*package*/ class BitmapFactory_Delegate {
 
-    // ------ Java delegates ------
-
-    @LayoutlibDelegate
-    /*package*/ static Bitmap finishDecode(Bitmap bm, Rect outPadding, Options opts) {
-        if (bm == null || opts == null) {
-            return bm;
-        }
-
-        final int density = opts.inDensity;
-        if (density == 0) {
-            return bm;
-        }
-
-        bm.setDensity(density);
-        final int targetDensity = opts.inTargetDensity;
-        if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity) {
-            return bm;
-        }
-
-        byte[] np = bm.getNinePatchChunk();
-        final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np);
-        // DELEGATE CHANGE: never scale 9-patch
-        if (opts.inScaled && isNinePatch == false) {
-            float scale = targetDensity / (float)density;
-            // TODO: This is very inefficient and should be done in native by Skia
-            final Bitmap oldBitmap = bm;
-            bm = Bitmap.createScaledBitmap(oldBitmap, (int) (bm.getWidth() * scale + 0.5f),
-                    (int) (bm.getHeight() * scale + 0.5f), true);
-            oldBitmap.recycle();
-
-            if (isNinePatch) {
-                np = nativeScaleNinePatch(np, scale, outPadding);
-                bm.setNinePatchChunk(np);
-            }
-            bm.setDensity(targetDensity);
-        }
-
-        return bm;
-    }
-
-
     // ------ Native Delegates ------
 
     @LayoutlibDelegate
     /*package*/ static Bitmap nativeDecodeStream(InputStream is, byte[] storage,
             Rect padding, Options opts) {
-        return nativeDecodeStream(is, storage, padding, opts, false, 1.f);
-    }
-
-    @LayoutlibDelegate
-    /*package*/ static  Bitmap nativeDecodeStream(InputStream is, byte[] storage,
-            Rect padding, Options opts, boolean applyScale, float scale) {
         Bitmap bm = null;
 
-        //TODO support rescaling
-
         Density density = Density.MEDIUM;
         Set<BitmapCreateFlags> bitmapCreateFlags = EnumSet.of(BitmapCreateFlags.MUTABLE);
         if (opts != null) {
@@ -157,13 +108,6 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static Bitmap nativeDecodeAsset(long asset, Rect padding, Options opts,
-            boolean applyScale, float scale) {
-        opts.inBitmap = null;
-        return null;
-    }
-
-    @LayoutlibDelegate
     /*package*/ static Bitmap nativeDecodeByteArray(byte[] data, int offset,
             int length, Options opts) {
         opts.inBitmap = null;
@@ -171,13 +115,6 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static byte[] nativeScaleNinePatch(byte[] chunk, float scale, Rect pad) {
-        // don't scale for now. This should not be called anyway since we re-implement
-        // BitmapFactory.finishDecode();
-        return chunk;
-    }
-
-    @LayoutlibDelegate
     /*package*/ static boolean nativeIsSeekable(FileDescriptor fd) {
         return true;
     }
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index f6abaa1..89d7e23 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -314,6 +314,13 @@
     }
 
     @LayoutlibDelegate
+    /*package*/ static void nativeReconfigure(long nativeBitmap, int width, int height,
+            int config, int allocSize) {
+        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
+                "Bitmap.reconfigure() is not supported", null /*data*/);
+    }
+
+    @LayoutlibDelegate
     /*package*/ static boolean nativeCompress(long nativeBitmap, int format, int quality,
             OutputStream stream, byte[] tempStorage) {
         Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
@@ -342,28 +349,6 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int nativeWidth(long nativeBitmap) {
-        // get the delegate from the native int.
-        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
-        if (delegate == null) {
-            return 0;
-        }
-
-        return delegate.mImage.getWidth();
-    }
-
-    @LayoutlibDelegate
-    /*package*/ static int nativeHeight(long nativeBitmap) {
-        // get the delegate from the native int.
-        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
-        if (delegate == null) {
-            return 0;
-        }
-
-        return delegate.mImage.getHeight();
-    }
-
-    @LayoutlibDelegate
     /*package*/ static int nativeRowBytes(long nativeBitmap) {
         // get the delegate from the native int.
         Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
@@ -408,19 +393,21 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int nativeGetPixel(long nativeBitmap, int x, int y) {
+    /*package*/ static int nativeGetPixel(long nativeBitmap, int x, int y,
+            boolean isPremultiplied) {
         // get the delegate from the native int.
         Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
         if (delegate == null) {
             return 0;
         }
 
+        // TODO: Support isPremultiplied.
         return delegate.mImage.getRGB(x, y);
     }
 
     @LayoutlibDelegate
     /*package*/ static void nativeGetPixels(long nativeBitmap, int[] pixels, int offset,
-            int stride, int x, int y, int width, int height) {
+            int stride, int x, int y, int width, int height, boolean isPremultiplied) {
         Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
         if (delegate == null) {
             return;
@@ -431,7 +418,8 @@
 
 
     @LayoutlibDelegate
-    /*package*/ static void nativeSetPixel(long nativeBitmap, int x, int y, int color) {
+    /*package*/ static void nativeSetPixel(long nativeBitmap, int x, int y, int color,
+            boolean isPremultiplied) {
         Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
         if (delegate == null) {
             return;
@@ -442,7 +430,7 @@
 
     @LayoutlibDelegate
     /*package*/ static void nativeSetPixels(long nativeBitmap, int[] colors, int offset,
-            int stride, int x, int y, int width, int height) {
+            int stride, int x, int y, int width, int height, boolean isPremultiplied) {
         Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
         if (delegate == null) {
             return;
diff --git a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
index a5c52e55..38745ce 100644
--- a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
@@ -167,6 +167,7 @@
         return sManager.addNewDelegate(newDelegate);
     }
 
+    @LayoutlibDelegate
     /*package*/ static void nativeFinalize(long chunk) {
         sManager.removeJavaReferenceFor(chunk);
     }
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index f3b56d9..6f6ef20 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -401,17 +401,17 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_addPath(long nPath, int src, float dx, float dy) {
+    /*package*/ static void native_addPath(long nPath, long src, float dx, float dy) {
         addPath(nPath, src, AffineTransform.getTranslateInstance(dx, dy));
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_addPath(long nPath, int src) {
+    /*package*/ static void native_addPath(long nPath, long src) {
         addPath(nPath, src, null /*transform*/);
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_addPath(long nPath, int src, long matrix) {
+    /*package*/ static void native_addPath(long nPath, long src, long matrix) {
         Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix);
         if (matrixDelegate == null) {
             return;
@@ -474,6 +474,12 @@
     }
 
     @LayoutlibDelegate
+    /*package*/ static boolean native_op(long nPath1, long nPath2, int op, long result) {
+        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "Path.op() not supported", null);
+        return false;
+    }
+
+    @LayoutlibDelegate
     /*package*/ static void finalizer(long nPath) {
         sManager.removeJavaReferenceFor(nPath);
     }
diff --git a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java b/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java
index fd594f7..5f0d98b 100644
--- a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java
@@ -33,11 +33,6 @@
     private static long sBootTime = System.currentTimeMillis();
     private static long sBootTimeNano = System.nanoTime();
 
-    @LayoutlibDelegate
-    /*package*/ static boolean setCurrentTimeMillis(long millis) {
-        return true;
-    }
-
     /**
      * Returns milliseconds since boot, not counting time spent in deep sleep.
      * <b>Note:</b> This value may get reset occasionally (before it would
diff --git a/tools/layoutlib/bridge/src/libcore/icu/DateIntervalFormat_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/DateIntervalFormat_Delegate.java
index a773d93..d94c205 100644
--- a/tools/layoutlib/bridge/src/libcore/icu/DateIntervalFormat_Delegate.java
+++ b/tools/layoutlib/bridge/src/libcore/icu/DateIntervalFormat_Delegate.java
@@ -21,6 +21,7 @@
 import com.android.ide.common.rendering.api.LayoutLog;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
 import com.ibm.icu.text.DateIntervalFormat;
 import com.ibm.icu.util.DateInterval;
 import com.ibm.icu.util.TimeZone;
@@ -38,6 +39,7 @@
 
     // ---- native methods ----
 
+    @LayoutlibDelegate
     /*package*/static String formatDateInterval(long address, long fromDate, long toDate) {
         DateIntervalFormat_Delegate delegate = sManager.getDelegate((int)address);
         if (delegate == null) {
@@ -52,6 +54,7 @@
         return sb.toString();
     }
 
+    @LayoutlibDelegate
     /*package*/ static long createDateIntervalFormat(String skeleton, String localeName,
             String tzName) {
         TimeZone prevDefaultTz = TimeZone.getDefault();
@@ -63,6 +66,7 @@
         return sManager.addNewDelegate(newDelegate);
     }
 
+    @LayoutlibDelegate
     /*package*/ static void destroyDateIntervalFormat(long address) {
         sManager.removeJavaReferenceFor((int)address);
     }
diff --git a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
index 06ae804..998b08b 100644
--- a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
+++ b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
@@ -46,7 +46,7 @@
     // --- Native methods accessing ICU's database.
 
     @LayoutlibDelegate
-    /*package*/ static String getBestDateTimePattern(String skeleton, String localeName) {
+    /*package*/ static String getBestDateTimePatternNative(String skeleton, String localeName) {
         return DateTimePatternGenerator.getInstance(new ULocale(localeName))
                 .getBestPattern(skeleton);
     }
@@ -137,6 +137,11 @@
     }
 
     @LayoutlibDelegate
+    /*package*/ static String getDisplayScriptNative(String variantCode, String locale) {
+        return "";
+    }
+
+    @LayoutlibDelegate
     /*package*/ static String getISO3CountryNative(String locale) {
         return "";
     }
@@ -166,8 +171,19 @@
         return Locale.getISOCountries();
     }
 
+
     @LayoutlibDelegate
-    /*package*/ static boolean initLocaleDataImpl(String locale, LocaleData result) {
+    /*package*/ static String localeForLanguageTag(String languageTag, boolean strict) {
+        return "";
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static String languageTagForLocale(String locale) {
+        return "";
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static boolean initLocaleDataNative(String locale, LocaleData result) {
 
         // Used by Calendar.
         result.firstDayOfWeek = Integer.valueOf(1);
@@ -215,7 +231,7 @@
         result.percent = '%';
         result.perMill = '\u2030';
         result.monetarySeparator = ' ';
-        result.minusSign = '-';
+        result.minusSign = "-";
         result.exponentSeparator = "e";
         result.infinity = "\u221E";
         result.NaN = "NaN";
diff --git a/tools/preload/Android.mk b/tools/preload/Android.mk
index f325870..14a4547 100644
--- a/tools/preload/Android.mk
+++ b/tools/preload/Android.mk
@@ -20,4 +20,4 @@
 
 include $(BUILD_HOST_JAVA_LIBRARY)
 
-include $(call all-subdir-makefiles)
+include $(call all-makefiles-under,$(LOCAL_PATH))