Merge "Make misc config directory during user creation"
diff --git a/Android.mk b/Android.mk
index 1db4365..614e76d7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -283,7 +283,7 @@
 			$(framework_res_source_path)/com/android/internal/R.java
 
 LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := bouncycastle conscrypt core core-junit ext okhttp
+LOCAL_JAVA_LIBRARIES := core-libart conscrypt okhttp core-junit bouncycastle ext
 
 LOCAL_MODULE := framework-base
 
@@ -489,9 +489,9 @@
 	$(framework_res_source_path)/com/android/internal/R.java
 
 framework_docs_LOCAL_API_CHECK_JAVA_LIBRARIES := \
-	bouncycastle \
+	core-libart \
 	conscrypt \
-	core \
+	bouncycastle \
 	okhttp \
 	ext \
 	framework \
@@ -529,7 +529,7 @@
     -since $(SRC_API_DIR)/17.txt 17 \
     -since $(SRC_API_DIR)/18.txt 18 \
     -since $(SRC_API_DIR)/19.txt 19 \
-		-werror -hide 113 \
+		-werror -hide 111 -hide 113 \
 		-overview $(LOCAL_PATH)/core/java/overview.html
 
 framework_docs_LOCAL_API_CHECK_ADDITIONAL_JAVA_DIR:= \
@@ -796,7 +796,7 @@
 LOCAL_SRC_FILES := $(ext_src_files)
 
 LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core
+LOCAL_JAVA_LIBRARIES := core-libart
 LOCAL_JAVA_RESOURCE_DIRS := $(ext_res_dirs)
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE := ext
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index cb453e2..badaec3 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -1188,6 +1188,7 @@
         data.writeInt(level);
         mRemote.transact(SCHEDULE_TRIM_MEMORY_TRANSACTION, data, null,
                 IBinder.FLAG_ONEWAY);
+        data.recycle();
     }
 
     public void dumpMemInfo(FileDescriptor fd, Debug.MemoryInfo mem, boolean checkin,
diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java
index 6e99899..652ad23 100644
--- a/core/java/android/app/FragmentTransaction.java
+++ b/core/java/android/app/FragmentTransaction.java
@@ -106,7 +106,7 @@
     public abstract FragmentTransaction detach(Fragment fragment);
 
     /**
-     * Re-attach a fragment after it had previously been deatched from
+     * Re-attach a fragment after it had previously been detached from
      * the UI with {@link #detach(Fragment)}.  This
      * causes its view hierarchy to be re-created, attached to the UI,
      * and displayed.
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index ab82531..49ed27b 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1071,7 +1071,7 @@
     public static final int WIPE_EXTERNAL_STORAGE = 0x0001;
 
     /**
-     * Ask the user date be wiped.  This will cause the device to reboot,
+     * Ask the user data be wiped.  This will cause the device to reboot,
      * erasing all user data while next booting up.  External storage such
      * as SD cards will be also erased if the flag {@link #WIPE_EXTERNAL_STORAGE}
      * is set.
diff --git a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
index a9b7176..f665a001 100644
--- a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
+++ b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
@@ -91,7 +91,7 @@
         return sInstance;
     }
 
-    public Object Clone() throws CloneNotSupportedException {
+    public Object clone() throws CloneNotSupportedException {
         throw new CloneNotSupportedException();
     }
 
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 3d9daca..3db9ddb 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1569,7 +1569,7 @@
 
             String locale = null;
             if (mConfiguration.locale != null) {
-                locale = mConfiguration.locale.toLanguageTag();
+                locale = adjustLanguageTag(localeToLanguageTag(mConfiguration.locale));
             }
             int width, height;
             if (mMetrics.widthPixels >= mMetrics.heightPixels) {
@@ -1650,6 +1650,47 @@
         }
     }
 
+    // Locale.toLanguageTag() is not available in Java6. LayoutLib overrides
+    // this method to enable users to use Java6.
+    private String localeToLanguageTag(Locale locale) {
+        return locale.toLanguageTag();
+    }
+
+    /**
+     * {@code Locale.toLanguageTag} will transform the obsolete (and deprecated)
+     * language codes "in", "ji" and "iw" to "id", "yi" and "he" respectively.
+     *
+     * All released versions of android prior to "L" used the deprecated language
+     * tags, so we will need to support them for backwards compatibility.
+     *
+     * Note that this conversion needs to take place *after* the call to
+     * {@code toLanguageTag} because that will convert all the deprecated codes to
+     * the new ones, even if they're set manually.
+     */
+    private static String adjustLanguageTag(String languageTag) {
+        final int separator = languageTag.indexOf('-');
+        final String language;
+        final String remainder;
+
+        if (separator == -1) {
+            language = languageTag;
+            remainder = "";
+        } else {
+            language = languageTag.substring(0, separator);
+            remainder = languageTag.substring(separator);
+        }
+
+        if ("id".equals(language)) {
+            return "in" + remainder;
+        } else if ("yi".equals(language)) {
+            return "ji" + remainder;
+        } else if ("he".equals(language)) {
+            return "iw" + remainder;
+        } else {
+            return languageTag;
+        }
+    }
+
     /**
      * Update the system resources configuration if they have previously
      * been initialized.
diff --git a/core/java/android/hardware/ConsumerIrManager.java b/core/java/android/hardware/ConsumerIrManager.java
index 77087814..6d29212 100644
--- a/core/java/android/hardware/ConsumerIrManager.java
+++ b/core/java/android/hardware/ConsumerIrManager.java
@@ -65,7 +65,7 @@
     }
 
     /**
-     * Tansmit and infrared pattern
+     * Transmit an infrared pattern
      * <p>
      * This method is synchronous; when it returns the pattern has
      * been transmitted. Only patterns shorter than 2 seconds will
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 70c8750..2aff5f2 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -929,6 +929,23 @@
     }
 
     /**
+     * Get the set of tethered dhcp ranges.
+     *
+     * @return an array of 0 or more Strings of tethered dhcp ranges.
+     *
+     * <p>This method requires the call to hold the permission
+     * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
+     * {@hide}
+     */
+    public String[] getTetheredDhcpRanges() {
+        try {
+            return mService.getTetheredDhcpRanges();
+        } catch (RemoteException e) {
+            return new String[0];
+        }
+    }
+
+    /**
      * Get the set of tethered interfaces.
      *
      * @return an array of 0 or more String of currently tethered interface names.
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index cc8c771..5ed2409 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -186,7 +186,7 @@
         return sInstance;
     }
 
-    public Object Clone() throws CloneNotSupportedException {
+    public Object clone() throws CloneNotSupportedException {
         throw new CloneNotSupportedException();
     }
 
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 4bca7fe..3bfd88e 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -91,6 +91,8 @@
 
     String[] getTetherableIfaces();
 
+    String[] getTetheredDhcpRanges();
+
     String[] getTetheredIfaces();
 
     String[] getTetheringErroredIfaces();
diff --git a/core/java/android/net/http/CertificateChainValidator.java b/core/java/android/net/http/CertificateChainValidator.java
index d06355d..bf3fe02 100644
--- a/core/java/android/net/http/CertificateChainValidator.java
+++ b/core/java/android/net/http/CertificateChainValidator.java
@@ -16,6 +16,9 @@
 
 package android.net.http;
 
+import com.android.org.conscrypt.SSLParametersImpl;
+import com.android.org.conscrypt.TrustManagerImpl;
+
 import android.util.Slog;
 
 import java.io.ByteArrayInputStream;
@@ -37,7 +40,7 @@
 import javax.net.ssl.SSLSocket;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509ExtendedTrustManager;
+import javax.net.ssl.X509TrustManager;
 
 /**
  * Class responsible for all server certificate validation functionality
@@ -60,7 +63,7 @@
                 .getDefaultHostnameVerifier();
     }
 
-    private X509ExtendedTrustManager mTrustManager;
+    private X509TrustManager mTrustManager;
 
     /**
      * @return The singleton instance of the certificates chain validator
@@ -78,8 +81,8 @@
             TrustManagerFactory tmf = TrustManagerFactory.getInstance("X.509");
             tmf.init((KeyStore) null);
             for (TrustManager tm : tmf.getTrustManagers()) {
-                if (tm instanceof X509ExtendedTrustManager) {
-                    mTrustManager = (X509ExtendedTrustManager) tm;
+                if (tm instanceof X509TrustManager) {
+                    mTrustManager = (X509TrustManager) tm;
                 }
             }
         } catch (NoSuchAlgorithmException e) {
@@ -90,7 +93,7 @@
 
         if (mTrustManager == null) {
             throw new RuntimeException(
-                    "None of the X.509 TrustManagers are X509ExtendedTrustManager");
+                    "None of the X.509 TrustManagers are X509TrustManager");
         }
     }
 
@@ -225,8 +228,13 @@
         }
 
         try {
-            getInstance().getTrustManager().checkServerTrusted(chain, authType,
-                    new DelegatingSocketWrapper(domain));
+            X509TrustManager x509TrustManager = SSLParametersImpl.getDefaultX509TrustManager();
+            if (x509TrustManager instanceof TrustManagerImpl) {
+                TrustManagerImpl trustManager = (TrustManagerImpl) x509TrustManager;
+                trustManager.checkServerTrusted(chain, authType, domain);
+            } else {
+                x509TrustManager.checkServerTrusted(chain, authType);
+            }
             return null;  // No errors.
         } catch (GeneralSecurityException e) {
             if (HttpLog.LOGV) {
@@ -238,9 +246,9 @@
     }
 
     /**
-     * Returns the platform default {@link X509ExtendedTrustManager}.
+     * Returns the platform default {@link X509TrustManager}.
      */
-    private X509ExtendedTrustManager getTrustManager() {
+    private X509TrustManager getTrustManager() {
         return mTrustManager;
     }
 
@@ -268,4 +276,4 @@
 
         throw new SSLHandshakeException(errorMessage);
     }
-}
\ No newline at end of file
+}
diff --git a/core/java/android/net/http/DelegatingSSLSession.java b/core/java/android/net/http/DelegatingSSLSession.java
index ff75b24..98fbe21 100644
--- a/core/java/android/net/http/DelegatingSSLSession.java
+++ b/core/java/android/net/http/DelegatingSSLSession.java
@@ -24,12 +24,11 @@
 import javax.net.ssl.SSLSession;
 import javax.net.ssl.SSLSessionContext;
 import javax.net.ssl.SSLSocket;
-import javax.net.ssl.X509ExtendedTrustManager;
+import javax.net.ssl.X509TrustManager;
 
 /**
- * This is used when only a {@code hostname} is available but usage of the new API
- * {@link X509ExtendedTrustManager#checkServerTrusted(X509Certificate[], String, Socket)}
- * requires a {@link SSLSocket}.
+ * This is only used when a {@code certificate} is available but usage
+ * requires a {@link SSLSession}.
  *
  * @hide
  */
@@ -37,19 +36,6 @@
     protected DelegatingSSLSession() {
     }
 
-    public static class HostnameWrap extends DelegatingSSLSession {
-        private final String mHostname;
-
-        public HostnameWrap(String hostname) {
-            mHostname = hostname;
-        }
-
-        @Override
-        public String getPeerHost() {
-            return mHostname;
-        }
-    }
-
     public static class CertificateWrap extends DelegatingSSLSession {
         private final Certificate mCertificate;
 
@@ -169,4 +155,4 @@
     public void removeValue(String name) {
         throw new UnsupportedOperationException();
     }
-}
\ No newline at end of file
+}
diff --git a/core/java/android/net/http/DelegatingSocketWrapper.java b/core/java/android/net/http/DelegatingSocketWrapper.java
deleted file mode 100644
index 230d017..0000000
--- a/core/java/android/net/http/DelegatingSocketWrapper.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.http;
-
-import java.io.IOException;
-
-import javax.net.ssl.HandshakeCompletedListener;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.X509ExtendedTrustManager;
-
-/**
- * This is used when only a {@code hostname} is available for
- * {@link X509ExtendedTrustManager#checkServerTrusted(java.security.cert.X509Certificate[], String, Socket)}
- * but we want to use the new API that requires a {@link SSLSocket}.
- */
-class DelegatingSocketWrapper extends SSLSocket {
-    private String hostname;
-
-    public DelegatingSocketWrapper(String hostname) {
-        this.hostname = hostname;
-    }
-
-    @Override
-    public String[] getSupportedCipherSuites() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public String[] getEnabledCipherSuites() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void setEnabledCipherSuites(String[] suites) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public String[] getSupportedProtocols() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public String[] getEnabledProtocols() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void setEnabledProtocols(String[] protocols) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public SSLSession getSession() {
-        return new DelegatingSSLSession.HostnameWrap(hostname);
-    }
-
-    @Override
-    public void addHandshakeCompletedListener(HandshakeCompletedListener listener) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void removeHandshakeCompletedListener(HandshakeCompletedListener listener) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void startHandshake() throws IOException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void setUseClientMode(boolean mode) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean getUseClientMode() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void setNeedClientAuth(boolean need) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void setWantClientAuth(boolean want) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean getNeedClientAuth() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean getWantClientAuth() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void setEnableSessionCreation(boolean flag) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean getEnableSessionCreation() {
-        throw new UnsupportedOperationException();
-    }
-}
\ No newline at end of file
diff --git a/core/java/android/net/http/X509TrustManagerExtensions.java b/core/java/android/net/http/X509TrustManagerExtensions.java
index d730a7b..e8ccc2b 100644
--- a/core/java/android/net/http/X509TrustManagerExtensions.java
+++ b/core/java/android/net/http/X509TrustManagerExtensions.java
@@ -24,7 +24,6 @@
 
 import javax.net.ssl.SSLParameters;
 import javax.net.ssl.SSLSocket;
-import javax.net.ssl.X509ExtendedTrustManager;
 import javax.net.ssl.X509TrustManager;
 
 /**
@@ -34,13 +33,6 @@
  * verification of certificate chains after they have been successfully verified
  * by the platform.
  * </p>
- * <p>
- * If the returned certificate list is not needed, see also
- * {@code X509ExtendedTrustManager#checkServerTrusted(X509Certificate[], String, java.net.Socket)}
- * where an {@link SSLSocket} can be used to verify the given hostname during
- * handshake using
- * {@code SSLParameters#setEndpointIdentificationAlgorithm(String)}.
- * </p>
  */
 public class X509TrustManagerExtensions {
 
@@ -73,7 +65,6 @@
      */
     public List<X509Certificate> checkServerTrusted(X509Certificate[] chain, String authType,
                                                     String host) throws CertificateException {
-        return mDelegate.checkServerTrusted(chain, authType,
-                new DelegatingSSLSession.HostnameWrap(host));
+        return mDelegate.checkServerTrusted(chain, authType, host);
     }
 }
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index af57507..fd1df92 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -1127,10 +1127,12 @@
 
     /**
      * Returns the value associated with the given key, or defaultValue if
-     * no mapping of the desired type exists for the given key.
+     * no mapping of the desired type exists for the given key or if a null
+     * value is explicitly associated with the given key.
      *
      * @param key a String, or null
-     * @param defaultValue Value to return if key does not exist
+     * @param defaultValue Value to return if key does not exist or if a null
+     *     value is associated with the given key.
      * @return the String value associated with the given key, or defaultValue
      *     if no valid String object is currently mapped to that key.
      */
@@ -1160,10 +1162,12 @@
 
     /**
      * Returns the value associated with the given key, or defaultValue if
-     * no mapping of the desired type exists for the given key.
+     * no mapping of the desired type exists for the given key or if a null
+     * value is explicitly associatd with the given key.
      *
      * @param key a String, or null
-     * @param defaultValue Value to return if key does not exist
+     * @param defaultValue Value to return if key does not exist or if a null
+     *     value is associated with the given key.
      * @return the CharSequence value associated with the given key, or defaultValue
      *     if no valid CharSequence object is currently mapped to that key.
      */
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index 51203a48..5ae03e1 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -343,7 +343,7 @@
     }
 
     /**
-     * Sets a Bundle of arbitrary data values. Use arg1 and arg1 members 
+     * Sets a Bundle of arbitrary data values. Use arg1 and arg2 members
      * as a lower cost way to send a few simple integer values, if you can.
      * @see #getData() 
      * @see #peekData()
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index f69cad0..87e61b9 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -40,6 +40,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.Arrays;
 
 /**
  * The Media provider contains meta data for all available media on both internal
@@ -655,6 +656,7 @@
                         if (sThumbBuf == null) {
                             sThumbBuf = new byte[MiniThumbFile.BYTES_PER_MINTHUMB];
                         }
+                        Arrays.fill(sThumbBuf, (byte)0);
                         if (thumbFile.getMiniThumbFromFile(origId, sThumbBuf) != null) {
                             bitmap = BitmapFactory.decodeByteArray(sThumbBuf, 0, sThumbBuf.length);
                             if (bitmap == null) {
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index d1f35dd..9fec9a1 100755
--- a/core/java/android/text/format/DateFormat.java
+++ b/core/java/android/text/format/DateFormat.java
@@ -195,7 +195,7 @@
      * @return a string pattern suitable for use with {@link java.text.SimpleDateFormat}.
      */
     public static String getBestDateTimePattern(Locale locale, String skeleton) {
-        return ICU.getBestDateTimePattern(skeleton, locale.toString());
+        return ICU.getBestDateTimePattern(skeleton, locale);
     }
 
     /**
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index 33964a0..707edef 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -62,10 +62,7 @@
      */
     public static TimeZone getTimeZone(int offset, boolean dst, long when, String country) {
         TimeZone best = null;
-
-        Resources r = Resources.getSystem();
-        XmlResourceParser parser = r.getXml(com.android.internal.R.xml.time_zones_by_country);
-        Date d = new Date(when);
+        final Date d = new Date(when);
 
         TimeZone current = TimeZone.getDefault();
         String currentName = current.getID();
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index 67a94be..2a8523f 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -314,8 +314,8 @@
      */
     public ViewPropertyAnimator setStartDelay(long startDelay) {
         if (startDelay < 0) {
-            throw new IllegalArgumentException("Animators cannot have negative duration: " +
-                    startDelay);
+            throw new IllegalArgumentException("Animators cannot have negative start " +
+                "delay: " + startDelay);
         }
         mStartDelaySet = true;
         mStartDelay = startDelay;
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 26c5732..7f6823d 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -59,7 +59,7 @@
 import java.util.Locale;
 
 /**
- * A widget that enables the user to select a number form a predefined range.
+ * A widget that enables the user to select a number from a predefined range.
  * There are two flavors of this widget and which one is presented to the user
  * depends on the current theme.
  * <ul>
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 0d3df51..b290744 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1709,7 +1709,9 @@
         Parcel p = Parcel.obtain();
         writeToParcel(p, 0);
         p.setDataPosition(0);
-        return new RemoteViews(p);
+        RemoteViews rv = new RemoteViews(p);
+        p.recycle();
+        return rv;
     }
 
     public String getPackage() {
diff --git a/core/java/com/android/internal/app/LocalePicker.java b/core/java/com/android/internal/app/LocalePicker.java
index 043964f..f5c498a 100644
--- a/core/java/com/android/internal/app/LocalePicker.java
+++ b/core/java/com/android/internal/app/LocalePicker.java
@@ -37,6 +37,8 @@
 
 import java.text.Collator;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 import java.util.Locale;
 import java.util.ArrayList;
 
@@ -108,8 +110,9 @@
             final int layoutId, final int fieldId, final boolean isInDeveloperMode) {
         final Resources resources = context.getResources();
 
-        ArrayList<String> localeList = new ArrayList<String>(Arrays.asList(
-                Resources.getSystem().getAssets().getLocales()));
+        String[] locales = Resources.getSystem().getAssets().getLocales();
+        List<String> localeList = new ArrayList<String>(locales.length);
+        Collections.addAll(localeList, locales);
         if (isInDeveloperMode) {
             if (!localeList.contains("zz_ZZ")) {
                 localeList.add("zz_ZZ");
@@ -120,78 +123,62 @@
          *	}
          */
         }
-        String[] locales = new String[localeList.size()];
-        locales = localeList.toArray(locales);
 
+        Collections.sort(localeList);
         final String[] specialLocaleCodes = resources.getStringArray(R.array.special_locale_codes);
         final String[] specialLocaleNames = resources.getStringArray(R.array.special_locale_names);
-        Arrays.sort(locales);
-        final int origSize = locales.length;
-        final LocaleInfo[] preprocess = new LocaleInfo[origSize];
-        int finalSize = 0;
-        for (int i = 0 ; i < origSize; i++ ) {
-            final String s = locales[i];
-            final int len = s.length();
-            if (len == 5) {
-                String language = s.substring(0, 2);
-                String country = s.substring(3, 5);
-                final Locale l = new Locale(language, country);
 
-                if (finalSize == 0) {
+        final ArrayList<LocaleInfo> localeInfos = new ArrayList<LocaleInfo>(localeList.size());
+        for (String locale : localeList) {
+            final Locale l = Locale.forLanguageTag(locale.replace('_', '-'));
+            if (l == null || "und".equals(l.getLanguage())
+                    || l.getLanguage().isEmpty() || l.getCountry().isEmpty()) {
+                continue;
+            }
+
+            if (localeInfos.isEmpty()) {
+                if (DEBUG) {
+                    Log.v(TAG, "adding initial "+ toTitleCase(l.getDisplayLanguage(l)));
+                }
+                localeInfos.add(new LocaleInfo(toTitleCase(l.getDisplayLanguage(l)), l));
+            } else {
+                // check previous entry:
+                //  same lang and a country -> upgrade to full name and
+                //    insert ours with full name
+                //  diff lang -> insert ours with lang-only name
+                final LocaleInfo previous = localeInfos.get(localeInfos.size() - 1);
+                if (previous.locale.getLanguage().equals(l.getLanguage()) &&
+                        !previous.locale.getLanguage().equals("zz")) {
                     if (DEBUG) {
-                        Log.v(TAG, "adding initial "+ toTitleCase(l.getDisplayLanguage(l)));
+                        Log.v(TAG, "backing up and fixing " + previous.label + " to " +
+                                getDisplayName(previous.locale, specialLocaleCodes, specialLocaleNames));
                     }
-                    preprocess[finalSize++] =
-                            new LocaleInfo(toTitleCase(l.getDisplayLanguage(l)), l);
+                    previous.label = toTitleCase(getDisplayName(
+                            previous.locale, specialLocaleCodes, specialLocaleNames));
+                    if (DEBUG) {
+                        Log.v(TAG, "  and adding "+ toTitleCase(
+                                getDisplayName(l, specialLocaleCodes, specialLocaleNames)));
+                    }
+                    localeInfos.add(new LocaleInfo(toTitleCase(
+                            getDisplayName(l, specialLocaleCodes, specialLocaleNames)), l));
                 } else {
-                    // check previous entry:
-                    //  same lang and a country -> upgrade to full name and
-                    //    insert ours with full name
-                    //  diff lang -> insert ours with lang-only name
-                    if (preprocess[finalSize-1].locale.getLanguage().equals(
-                            language) &&
-                            !preprocess[finalSize-1].locale.getLanguage().equals("zz")) {
-                        if (DEBUG) {
-                            Log.v(TAG, "backing up and fixing "+
-                                    preprocess[finalSize-1].label+" to "+
-                                    getDisplayName(preprocess[finalSize-1].locale,
-                                            specialLocaleCodes, specialLocaleNames));
-                        }
-                        preprocess[finalSize-1].label = toTitleCase(
-                                getDisplayName(preprocess[finalSize-1].locale,
-                                        specialLocaleCodes, specialLocaleNames));
-                        if (DEBUG) {
-                            Log.v(TAG, "  and adding "+ toTitleCase(
-                                    getDisplayName(l, specialLocaleCodes, specialLocaleNames)));
-                        }
-                        preprocess[finalSize++] =
-                                new LocaleInfo(toTitleCase(
-                                        getDisplayName(
-                                                l, specialLocaleCodes, specialLocaleNames)), l);
+                    String displayName;
+                    if (locale.equals("zz_ZZ")) {
+                        displayName = "[Developer] Accented English";
+                    } else if (locale.equals("zz_ZY")) {
+                        displayName = "[Developer] Fake Bi-Directional";
                     } else {
-                        String displayName;
-                        if (s.equals("zz_ZZ")) {
-                            displayName = "[Developer] Accented English";
-                        } else if (s.equals("zz_ZY")) {
-                            displayName = "[Developer] Fake Bi-Directional";
-                        } else {
-                            displayName = toTitleCase(l.getDisplayLanguage(l));
-                        }
-                        if (DEBUG) {
-                            Log.v(TAG, "adding "+displayName);
-                        }
-                        preprocess[finalSize++] = new LocaleInfo(displayName, l);
+                        displayName = toTitleCase(l.getDisplayLanguage(l));
                     }
+                    if (DEBUG) {
+                        Log.v(TAG, "adding "+displayName);
+                    }
+                    localeInfos.add(new LocaleInfo(displayName, l));
                 }
             }
         }
 
-        final LocaleInfo[] localeInfos = new LocaleInfo[finalSize];
-        for (int i = 0; i < finalSize; i++) {
-            localeInfos[i] = preprocess[i];
-        }
-        Arrays.sort(localeInfos);
-
+        Collections.sort(localeInfos);
         final LayoutInflater inflater =
                 (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         return new ArrayAdapter<LocaleInfo>(context, layoutId, fieldId, localeInfos) {
diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java
index dab3aff..832829d 100644
--- a/core/java/com/android/internal/content/NativeLibraryHelper.java
+++ b/core/java/com/android/internal/content/NativeLibraryHelper.java
@@ -19,6 +19,7 @@
 import android.content.pm.PackageManager;
 import android.util.Slog;
 
+import java.io.Closeable;
 import java.io.File;
 import java.io.IOException;
 
@@ -39,20 +40,29 @@
      *
      * @hide
      */
-    public static class ApkHandle {
+    public static class ApkHandle implements Closeable {
         final String apkPath;
         final long apkHandle;
 
-        public ApkHandle(String path) {
-            apkPath = path;
-            apkHandle = nativeOpenApk(apkPath);
+        public static ApkHandle create(String path) throws IOException {
+            final long handle = nativeOpenApk(path);
+            if (handle == 0) {
+                throw new IOException("Unable to open APK: " + path);
+            }
+
+            return new ApkHandle(path, handle);
         }
 
-        public ApkHandle(File apkFile) {
-            apkPath = apkFile.getPath();
-            apkHandle = nativeOpenApk(apkPath);
+        public static ApkHandle create(File path) throws IOException {
+            return create(path.getAbsolutePath());
         }
 
+        private ApkHandle(String apkPath, long apkHandle) {
+            this.apkPath = apkPath;
+            this.apkHandle = apkHandle;
+        }
+
+        @Override
         public void close() {
             nativeClose(apkHandle);
         }
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 5e7d6ef..4f80704 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -391,8 +391,8 @@
         property_get("ro.product.locale.language", propLang, "en");
         property_get("ro.product.locale.region", propRegn, "US");
     }
-    strncat(language, propLang, 2);
-    strncat(region, propRegn, 2);
+    strncat(language, propLang, 3);
+    strncat(region, propRegn, 3);
     //ALOGD("language=%s region=%s\n", language, region);
 }
 
@@ -436,6 +436,82 @@
 }
 
 /*
+ * Reads a "property" into "buffer" with a default of "defaultArg". If
+ * the property is non-empty, it is treated as a runtime option such
+ * as "-Xmx32m".
+ *
+ * The "runtimeArg" is a prefix for the option such as "-Xms" or "-Xmx".
+ *
+ * If an argument is found, it is added to mOptions.
+ *
+ * If an option is found, it is added to mOptions and true is
+ * returned. Otherwise false is returned.
+ */
+bool AndroidRuntime::parseRuntimeOption(const char* property,
+                                        char* buffer,
+                                        const char* runtimeArg,
+                                        const char* defaultArg)
+{
+    strcpy(buffer, runtimeArg);
+    size_t runtimeArgLen = strlen(runtimeArg);
+    property_get(property, buffer+runtimeArgLen, defaultArg);
+    if (buffer[runtimeArgLen] == '\0') {
+        return false;
+    }
+
+    JavaVMOption opt;
+    memset(&opt, 0, sizeof(opt));
+
+    opt.optionString = buffer;
+    mOptions.add(opt);
+
+    return true;
+}
+
+/*
+ * Reads a "property" into "buffer". If the property is non-empty, it
+ * is treated as a dex2oat compiler runtime option that should be
+ * passed as a quoted option, e.g. "-Ximage-compiler-option
+ * --runtime-arg -Ximage-compiler-option -Xmx32m".
+ *
+ * The "runtimeArg" is a prefix for the option such as "-Xms" or "-Xmx".
+ *
+ * The "quotingArg" should be "-Ximage-compiler-option" or "-Xcompiler-option".
+ *
+ * If an option is found, it is added to mOptions and true is
+ * returned. Otherwise false is returned.
+ */
+bool AndroidRuntime::parseCompilerRuntimeOption(const char* property,
+                                                char* buffer,
+                                                const char* runtimeArg,
+                                                const char* quotingArg)
+{
+    strcpy(buffer, runtimeArg);
+    size_t runtimeArgLen = strlen(runtimeArg);
+    property_get(property, buffer+runtimeArgLen, "");
+    if (buffer[runtimeArgLen] == '\0') {
+        return false;
+    }
+
+    JavaVMOption opt;
+    memset(&opt, 0, sizeof(opt));
+
+    opt.optionString = quotingArg;
+    mOptions.add(opt);
+
+    opt.optionString = "--runtime-arg";
+    mOptions.add(opt);
+
+    opt.optionString = quotingArg;
+    mOptions.add(opt);
+
+    opt.optionString = buffer;
+    mOptions.add(opt);
+
+    return true;
+}
+
+/*
  * Start the Dalvik Virtual Machine.
  *
  * Various arguments, most determined by system properties, are passed in.
@@ -457,7 +533,7 @@
     JavaVMInitArgs initArgs;
     JavaVMOption opt;
     char propBuf[PROPERTY_VALUE_MAX];
-    char stackTraceFileBuf[PROPERTY_VALUE_MAX];
+    char stackTraceFileBuf[sizeof("-Xstacktracefile:")-1 + PROPERTY_VALUE_MAX];
     char dexoptFlagsBuf[PROPERTY_VALUE_MAX];
     char enableAssertBuf[sizeof("-ea:")-1 + PROPERTY_VALUE_MAX];
     char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];
@@ -471,31 +547,35 @@
     char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX];
     char jitcodecachesizeOptsBuf[sizeof("-Xjitcodecachesize:")-1 + PROPERTY_VALUE_MAX];
     char dalvikVmLibBuf[PROPERTY_VALUE_MAX];
+    char dex2oatXmsImageFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
+    char dex2oatXmxImageFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
+    char dex2oatXmsFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
+    char dex2oatXmxFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
     char dex2oatFlagsBuf[PROPERTY_VALUE_MAX];
     char dex2oatImageFlagsBuf[PROPERTY_VALUE_MAX];
     char extraOptsBuf[PROPERTY_VALUE_MAX];
-    char* stackTraceFile = NULL;
-    bool checkJni = false;
-    bool checkDexSum = false;
-    bool logStdio = false;
     enum {
       kEMDefault,
       kEMIntPortable,
       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 profile_top_k_threshold[sizeof("-Xprofile-top-k-threshold") + PROPERTY_VALUE_MAX];
-    char profile_top_k_change_threshold[sizeof("-Xprofile-top-k-change-threshold") + PROPERTY_VALUE_MAX];
+    char profilePeriod[sizeof("-Xprofile-period:")-1 + PROPERTY_VALUE_MAX];
+    char profileDuration[sizeof("-Xprofile-duration:")-1 + PROPERTY_VALUE_MAX];
+    char profileInterval[sizeof("-Xprofile-interval:")-1 + PROPERTY_VALUE_MAX];
+    char profileBackoff[sizeof("-Xprofile-backoff:")-1 + PROPERTY_VALUE_MAX];
+    char profileTopKThreshold[sizeof("-Xprofile-top-k-threshold:")-1 + PROPERTY_VALUE_MAX];
+    char profileTopKChangeThreshold[sizeof("-Xprofile-top-k-change-threshold:")-1 +
+                                    PROPERTY_VALUE_MAX];
+    char profileType[sizeof("-Xprofile-type:")-1 + PROPERTY_VALUE_MAX];
+    char profileMaxStackDepth[sizeof("-Xprofile-max-stack-depth:")-1 + 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];
+    char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:")-1 + PROPERTY_VALUE_MAX];
+    char jitOpBuf[sizeof("-Xjitop:")-1 + PROPERTY_VALUE_MAX];
+    char jitMethodBuf[sizeof("-Xjitmethod:")-1 + PROPERTY_VALUE_MAX];
 
+    bool checkJni = false;
     property_get("dalvik.vm.checkjni", propBuf, "");
     if (strcmp(propBuf, "true") == 0) {
         checkJni = true;
@@ -506,6 +586,20 @@
             checkJni = true;
         }
     }
+    ALOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
+    if (checkJni) {
+        /* extended JNI checking */
+        opt.optionString = "-Xcheck:jni";
+        mOptions.add(opt);
+
+        /* set a cap on JNI global references */
+        opt.optionString = "-Xjnigreflimit:2000";
+        mOptions.add(opt);
+
+        /* with -Xcheck:jni, this provides a JNI function call trace */
+        //opt.optionString = "-verbose:jni";
+        //mOptions.add(opt);
+    }
 
     property_get("dalvik.vm.execution-mode", propBuf, "");
     if (strcmp(propBuf, "int:portable") == 0) {
@@ -516,23 +610,39 @@
         executionMode = kEMJitCompiler;
     }
 
-    property_get("dalvik.vm.stack-trace-file", stackTraceFileBuf, "");
+    parseRuntimeOption("dalvik.vm.stack-trace-file", stackTraceFileBuf, "-Xstacktracefile:");
 
     property_get("dalvik.vm.check-dex-sum", propBuf, "");
     if (strcmp(propBuf, "true") == 0) {
-        checkDexSum = true;
+        /* perform additional DEX checksum tests */
+        opt.optionString = "-Xcheckdexsum";
+        mOptions.add(opt);
     }
 
     property_get("log.redirect-stdio", propBuf, "");
     if (strcmp(propBuf, "true") == 0) {
-        logStdio = true;
+        /* convert stdout/stderr to log messages */
+        opt.optionString = "-Xlog-stdio";
+        mOptions.add(opt);
     }
 
     strcpy(enableAssertBuf, "-ea:");
-    property_get("dalvik.vm.enableassertions", enableAssertBuf+4, "");
+    property_get("dalvik.vm.enableassertions", enableAssertBuf+sizeof("-ea:")-1, "");
+    if (enableAssertBuf[sizeof("-ea:")-1] != '\0') {
+        /* accept "all" to mean "all classes and packages" */
+        if (strcmp(enableAssertBuf+sizeof("-ea:")-1, "all") == 0)
+            enableAssertBuf[3] = '\0'; // truncate to "-ea"
+        ALOGI("Assertions enabled: '%s'\n", enableAssertBuf);
+        opt.optionString = enableAssertBuf;
+        mOptions.add(opt);
+    } else {
+        ALOGV("Assertions disabled\n");
+    }
 
     strcpy(jniOptsBuf, "-Xjniopts:");
-    property_get("dalvik.vm.jniopts", jniOptsBuf+10, "");
+    if (parseRuntimeOption("dalvik.vm.jniopts", jniOptsBuf, "-Xjniopts:")) {
+        ALOGI("JNI options: '%s'\n", jniOptsBuf);
+    }
 
     /* route exit() to our handler */
     opt.extraInfo = (void*) runtime_exit;
@@ -561,54 +671,24 @@
      * The default starting and maximum size of the heap.  Larger
      * values should be specified in a product property override.
      */
-    strcpy(heapstartsizeOptsBuf, "-Xms");
-    property_get("dalvik.vm.heapstartsize", heapstartsizeOptsBuf+4, "4m");
-    opt.optionString = heapstartsizeOptsBuf;
-    mOptions.add(opt);
-    strcpy(heapsizeOptsBuf, "-Xmx");
-    property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");
-    opt.optionString = heapsizeOptsBuf;
-    mOptions.add(opt);
+    parseRuntimeOption("dalvik.vm.heapstartsize", heapstartsizeOptsBuf, "-Xms", "4m");
+    parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m");
 
     // Increase the main thread's interpreter stack size for bug 6315322.
     opt.optionString = "-XX:mainThreadStackSize=24K";
     mOptions.add(opt);
 
     // Set the max jit code cache size.  Note: size of 0 will disable the JIT.
-    strcpy(jitcodecachesizeOptsBuf, "-Xjitcodecachesize:");
-    property_get("dalvik.vm.jit.codecachesize", jitcodecachesizeOptsBuf+19,  NULL);
-    if (jitcodecachesizeOptsBuf[19] != '\0') {
-      opt.optionString = jitcodecachesizeOptsBuf;
-      mOptions.add(opt);
-    }
+    parseRuntimeOption("dalvik.vm.jit.codecachesize",
+                       jitcodecachesizeOptsBuf,
+                       "-Xjitcodecachesize:");
 
-    strcpy(heapgrowthlimitOptsBuf, "-XX:HeapGrowthLimit=");
-    property_get("dalvik.vm.heapgrowthlimit", heapgrowthlimitOptsBuf+20, "");
-    if (heapgrowthlimitOptsBuf[20] != '\0') {
-        opt.optionString = heapgrowthlimitOptsBuf;
-        mOptions.add(opt);
-    }
-
-    strcpy(heapminfreeOptsBuf, "-XX:HeapMinFree=");
-    property_get("dalvik.vm.heapminfree", heapminfreeOptsBuf+16, "");
-    if (heapminfreeOptsBuf[16] != '\0') {
-        opt.optionString = heapminfreeOptsBuf;
-        mOptions.add(opt);
-    }
-
-    strcpy(heapmaxfreeOptsBuf, "-XX:HeapMaxFree=");
-    property_get("dalvik.vm.heapmaxfree", heapmaxfreeOptsBuf+16, "");
-    if (heapmaxfreeOptsBuf[16] != '\0') {
-        opt.optionString = heapmaxfreeOptsBuf;
-        mOptions.add(opt);
-    }
-
-    strcpy(heaptargetutilizationOptsBuf, "-XX:HeapTargetUtilization=");
-    property_get("dalvik.vm.heaptargetutilization", heaptargetutilizationOptsBuf+26, "");
-    if (heaptargetutilizationOptsBuf[26] != '\0') {
-        opt.optionString = heaptargetutilizationOptsBuf;
-        mOptions.add(opt);
-    }
+    parseRuntimeOption("dalvik.vm.heapgrowthlimit", heapgrowthlimitOptsBuf, "-XX:HeapGrowthLimit=");
+    parseRuntimeOption("dalvik.vm.heapminfree", heapminfreeOptsBuf, "-XX:HeapMinFree=");
+    parseRuntimeOption("dalvik.vm.heapmaxfree", heapmaxfreeOptsBuf, "-XX:HeapMaxFree=");
+    parseRuntimeOption("dalvik.vm.heaptargetutilization",
+                       heaptargetutilizationOptsBuf,
+                       "-XX:HeapTargetUtilization=");
 
     property_get("ro.config.low_ram", propBuf, "");
     if (strcmp(propBuf, "true") == 0) {
@@ -616,19 +696,8 @@
       mOptions.add(opt);
     }
 
-    strcpy(gctypeOptsBuf, "-Xgc:");
-    property_get("dalvik.vm.gctype", gctypeOptsBuf+5, "");
-    if (gctypeOptsBuf[5] != '\0') {
-        opt.optionString = gctypeOptsBuf;
-        mOptions.add(opt);
-    }
-
-    strcpy(backgroundgcOptsBuf, "-XX:BackgroundGC=");
-    property_get("dalvik.vm.backgroundgctype", backgroundgcOptsBuf+sizeof("-XX:BackgroundGC=")-1, "");
-    if (backgroundgcOptsBuf[sizeof("-XX:BackgroundGC=")-1] != '\0') {
-        opt.optionString = backgroundgcOptsBuf;
-        mOptions.add(opt);
-    }
+    parseRuntimeOption("dalvik.vm.gctype", gctypeOptsBuf, "-Xgc:");
+    parseRuntimeOption("dalvik.vm.backgroundgctype", backgroundgcOptsBuf, "-XX:BackgroundGC=");
 
     /*
      * Enable or disable dexopt features, such as bytecode verification and
@@ -687,46 +756,15 @@
         "-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y";
     mOptions.add(opt);
 
-    ALOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
-    if (checkJni) {
-        /* extended JNI checking */
-        opt.optionString = "-Xcheck:jni";
-        mOptions.add(opt);
-
-        /* set a cap on JNI global references */
-        opt.optionString = "-Xjnigreflimit:2000";
-        mOptions.add(opt);
-
-        /* with -Xcheck:jni, this provides a JNI function call trace */
-        //opt.optionString = "-verbose:jni";
-        //mOptions.add(opt);
-    }
-
-    property_get("dalvik.vm.lockprof.threshold", propBuf, "");
-    if (strlen(propBuf) > 0) {
-      strcpy(lockProfThresholdBuf, "-Xlockprofthreshold:");
-      strcat(lockProfThresholdBuf, propBuf);
-      opt.optionString = lockProfThresholdBuf;
-      mOptions.add(opt);
-    }
+    parseRuntimeOption("dalvik.vm.lockprof.threshold",
+                       lockProfThresholdBuf,
+                       "-Xlockprofthreshold:");
 
     /* Force interpreter-only mode for selected opcodes. Eg "1-0a,3c,f1-ff" */
-    property_get("dalvik.vm.jit.op", propBuf, "");
-    if (strlen(propBuf) > 0) {
-        strcpy(jitOpBuf, "-Xjitop:");
-        strcat(jitOpBuf, propBuf);
-        opt.optionString = jitOpBuf;
-        mOptions.add(opt);
-    }
+    parseRuntimeOption("dalvik.vm.jit.op", jitOpBuf, "-Xjitop:");
 
     /* Force interpreter-only mode for selected methods */
-    property_get("dalvik.vm.jit.method", propBuf, "");
-    if (strlen(propBuf) > 0) {
-        strcpy(jitMethodBuf, "-Xjitmethod:");
-        strcat(jitMethodBuf, propBuf);
-        opt.optionString = jitMethodBuf;
-        mOptions.add(opt);
-    }
+    parseRuntimeOption("dalvik.vm.jit.method", jitMethodBuf, "-Xjitmethod:");
 
     if (executionMode == kEMIntPortable) {
         opt.optionString = "-Xint:portable";
@@ -739,58 +777,26 @@
         mOptions.add(opt);
     }
 
-    if (checkDexSum) {
-        /* perform additional DEX checksum tests */
-        opt.optionString = "-Xcheckdexsum";
-        mOptions.add(opt);
-    }
-
-    if (logStdio) {
-        /* convert stdout/stderr to log messages */
-        opt.optionString = "-Xlog-stdio";
-        mOptions.add(opt);
-    }
-
-    if (enableAssertBuf[4] != '\0') {
-        /* accept "all" to mean "all classes and packages" */
-        if (strcmp(enableAssertBuf+4, "all") == 0)
-            enableAssertBuf[3] = '\0';
-        ALOGI("Assertions enabled: '%s'\n", enableAssertBuf);
-        opt.optionString = enableAssertBuf;
-        mOptions.add(opt);
-    } else {
-        ALOGV("Assertions disabled\n");
-    }
-
-    if (jniOptsBuf[10] != '\0') {
-        ALOGI("JNI options: '%s'\n", jniOptsBuf);
-        opt.optionString = jniOptsBuf;
-        mOptions.add(opt);
-    }
-
-    if (stackTraceFileBuf[0] != '\0') {
-        static const char* stfOptName = "-Xstacktracefile:";
-
-        stackTraceFile = (char*) malloc(strlen(stfOptName) +
-            strlen(stackTraceFileBuf) +1);
-        strcpy(stackTraceFile, stfOptName);
-        strcat(stackTraceFile, stackTraceFileBuf);
-        opt.optionString = stackTraceFile;
-        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.2", dalvikVmLibBuf, "libart.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.
+        parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xms", dex2oatXmsImageFlagsBuf,
+                                   "-Xms", "-Ximage-compiler-option");
+        parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xmx", dex2oatXmxImageFlagsBuf,
+                                   "-Xmx", "-Ximage-compiler-option");
         property_get("dalvik.vm.image-dex2oat-flags", dex2oatImageFlagsBuf, "");
         parseExtraOpts(dex2oatImageFlagsBuf, "-Ximage-compiler-option");
+
+        // Extra options for DexClassLoader.
+        parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xms", dex2oatXmsFlagsBuf,
+                                   "-Xms", "-Xcompiler-option");
+        parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xmx", dex2oatXmxFlagsBuf,
+                                   "-Xmx", "-Xcompiler-option");
+        property_get("dalvik.vm.dex2oat-flags", dex2oatFlagsBuf, "");
+        parseExtraOpts(dex2oatFlagsBuf, "-Xcompiler-option");
     }
 
     /* extra options; parse this late so it overrides others */
@@ -820,57 +826,51 @@
             mOptions.add(opt);
         }
 
-        // Whether the profile should start upon app startup or be delayed by some random offset.
-        property_get("dalvik.vm.profile.start-immediately", propBuf, "0");
+        // Whether the profile should start upon app startup or be delayed by some random offset
+        // (in seconds) that is bound between 0 and a fixed value.
+        property_get("dalvik.vm.profile.start-immed", propBuf, "0");
         if (propBuf[0] == '1') {
             opt.optionString = "-Xprofile-start-immediately";
             mOptions.add(opt);
         }
 
         // Number of seconds during profile runs.
-        strcpy(profile_period, "-Xprofile-period:");
-        if (property_get("dalvik.vm.profile.period-secs", profile_period+17, NULL) > 0) {
-           opt.optionString = profile_period;
-           mOptions.add(opt);
-        }
+        parseRuntimeOption("dalvik.vm.profile.period-secs", profilePeriod, "-Xprofile-period:");
 
         // Length of each profile run (seconds).
-        strcpy(profile_duration, "-Xprofile-duration:");
-        if (property_get("dalvik.vm.profile.duration-secs", profile_duration+19, NULL) > 0) {
-            opt.optionString = profile_duration;
-            mOptions.add(opt);
-        }
+        parseRuntimeOption("dalvik.vm.profile.duration-secs",
+                           profileDuration,
+                           "-Xprofile-duration:");
 
         // Polling interval during profile run (microseconds).
-        strcpy(profile_interval, "-Xprofile-interval:");
-        if (property_get("dalvik.vm.profile.interval-us", profile_interval+19, NULL) > 0) {
-            opt.optionString = profile_interval;
-            mOptions.add(opt);
-        }
+        parseRuntimeOption("dalvik.vm.profile.interval-us", profileInterval, "-Xprofile-interval:");
 
         // Coefficient for period backoff.  The the period is multiplied
         // by this value after each profile run.
-        strcpy(profile_backoff, "-Xprofile-backoff:");
-        if (property_get("dalvik.vm.profile.backoff-coeff", profile_backoff+18, NULL) > 0) {
-            opt.optionString = profile_backoff;
-            mOptions.add(opt);
-        }
+        parseRuntimeOption("dalvik.vm.profile.backoff-coeff", profileBackoff, "-Xprofile-backoff:");
 
-        // Top K% of samples that are considered relevant when deciding if the app should be recompiled.
-        strcpy(profile_top_k_threshold, "-Xprofile-top-k-threshold:");
-        if (property_get("dalvik.vm.profile.top-k-thr", profile_top_k_threshold+26, NULL) > 0) {
-            opt.optionString = profile_top_k_threshold;
-            mOptions.add(opt);
-        }
+        // Top K% of samples that are considered relevant when
+        // deciding if the app should be recompiled.
+        parseRuntimeOption("dalvik.vm.profile.top-k-thr",
+                           profileTopKThreshold,
+                           "-Xprofile-top-k-threshold:");
 
-        // The threshold after which a change in the structure of the top K% profiled samples becomes significant
-        // and triggers recompilation. A change in profile is considered significant if X% (top-k-change-threshold)
-        // of the top K% (top-k-threshold property) samples has changed.
-        strcpy(profile_top_k_change_threshold, "-Xprofile-top-k-change-threshold:");
-        if (property_get("dalvik.vm.profile.top-k-ch-thr", profile_top_k_change_threshold+33, NULL) > 0) {
-            opt.optionString = profile_top_k_change_threshold;
-            mOptions.add(opt);
-        }
+        // The threshold after which a change in the structure of the
+        // top K% profiled samples becomes significant and triggers
+        // recompilation. A change in profile is considered
+        // significant if X% (top-k-change-threshold) of the top K%
+        // (top-k-threshold property) samples has changed.
+        parseRuntimeOption("dalvik.vm.profile.top-k-ch-thr",
+                           profileTopKChangeThreshold,
+                           "-Xprofile-top-k-change-threshold:");
+
+        // Type of profile data.
+        parseRuntimeOption("dalvik.vm.profiler.type", profileType, "-Xprofile-type:");
+
+        // Depth of bounded stack data
+        parseRuntimeOption("dalvik.vm.profile.max-stack-depth",
+                           profileMaxStackDepth,
+                           "-Xprofile-max-stack-depth:");
     }
 
     initArgs.version = JNI_VERSION_1_4;
@@ -893,7 +893,6 @@
     result = 0;
 
 bail:
-    free(stackTraceFile);
     return result;
 }
 
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index ab70f25..3f7df50 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -399,13 +399,46 @@
                                                         jshortArray javaAudioData,
                                                         jint offsetInShorts, jint sizeInShorts) {
 
-    jint read = android_media_AudioRecord_readInByteArray(env, thiz,
-                                                        (jbyteArray) javaAudioData,
-                                                        offsetInShorts*2, sizeInShorts*2);
-    if (read > 0) {
-        read /= 2;
+    jshort* recordBuff = NULL;
+    // get the audio recorder from which we'll read new audio samples
+    sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
+    if (lpRecorder == NULL) {
+        ALOGE("Unable to retrieve AudioRecord object, can't record");
+        return 0;
     }
-    return read;
+
+    if (!javaAudioData) {
+        ALOGE("Invalid Java array to store recorded audio, can't record");
+        return 0;
+    }
+
+    // get the pointer to where we'll record the audio
+    // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such
+    // a way that it becomes much more efficient. When doing so, we will have to prevent the
+    // AudioSystem callback to be called while in critical section (in case of media server
+    // process crash for instance)
+    recordBuff = (jshort *)env->GetShortArrayElements(javaAudioData, NULL);
+
+    if (recordBuff == NULL) {
+        ALOGE("Error retrieving destination for recorded audio data, can't record");
+        return 0;
+    }
+
+    // read the new audio data from the native AudioRecord object
+    const size_t recorderBuffSize = lpRecorder->frameCount()*lpRecorder->frameSize();
+    const size_t sizeInBytes = sizeInShorts * sizeof(short);
+    ssize_t readSize = lpRecorder->read(recordBuff + offsetInShorts * sizeof(short),
+                                        sizeInBytes > recorderBuffSize ?
+                                            recorderBuffSize : sizeInBytes);
+
+    env->ReleaseShortArrayElements(javaAudioData, recordBuff, 0);
+
+    if (readSize < 0) {
+        readSize = AUDIORECORD_ERROR_INVALID_OPERATION;
+    } else {
+        readSize /= sizeof(short);
+    }
+    return (jint) readSize;
 }
 
 // ----------------------------------------------------------------------------
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index a19d111..42feab4 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -129,6 +129,8 @@
     env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz,
                               "errorCallbackFromNative","(I)V"),
                               check_AudioSystem_Command(err));
+
+    env->DeleteLocalRef(clazz);
 }
 
 static jint
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index dc8d9d8..1bf42e9 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -595,13 +595,39 @@
                                                   jshortArray javaAudioData,
                                                   jint offsetInShorts, jint sizeInShorts,
                                                   jint javaAudioFormat) {
-    jint written = android_media_AudioTrack_native_write_byte(env, thiz,
-                                                 (jbyteArray) javaAudioData,
-                                                 offsetInShorts*2, sizeInShorts*2,
-                                                 javaAudioFormat);
-    if (written > 0) {
-        written /= 2;
+    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
+    if (lpTrack == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException",
+            "Unable to retrieve AudioTrack pointer for write()");
+        return 0;
     }
+
+    // get the pointer for the audio data from the java array
+    // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such
+    // a way that it becomes much more efficient. When doing so, we will have to prevent the
+    // AudioSystem callback to be called while in critical section (in case of media server
+    // process crash for instance)
+    jshort* cAudioData = NULL;
+    if (javaAudioData) {
+        cAudioData = (jshort *)env->GetShortArrayElements(javaAudioData, NULL);
+        if (cAudioData == NULL) {
+            ALOGE("Error retrieving source of audio data to play, can't play");
+            return 0; // out of memory or no data to load
+        }
+    } else {
+        ALOGE("NULL java array of audio data to play, can't play");
+        return 0;
+    }
+    jint written = writeToTrack(lpTrack, javaAudioFormat, (jbyte *)cAudioData,
+                                offsetInShorts * sizeof(short), sizeInShorts * sizeof(short));
+    env->ReleaseShortArrayElements(javaAudioData, cAudioData, 0);
+
+    if (written > 0) {
+        written /= sizeof(short);
+    }
+    //ALOGV("write wrote %d (tried %d) shorts in the native AudioTrack with offset %d",
+    //     (int)written, (int)(sizeInShorts), (int)offsetInShorts);
+
     return written;
 }
 
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 86207f0..87ee618 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -174,21 +174,21 @@
 
     ssize_t pss = memtrack_proc_graphics_pss(p);
     if (pss < 0) {
-        ALOGW("failed to get graphics pss: %d", pss);
+        ALOGW("failed to get graphics pss: %zd", pss);
         return pss;
     }
     graphics_mem->graphics = pss / 1024;
 
     pss = memtrack_proc_gl_pss(p);
     if (pss < 0) {
-        ALOGW("failed to get gl pss: %d", pss);
+        ALOGW("failed to get gl pss: %zd", pss);
         return pss;
     }
     graphics_mem->gl = pss / 1024;
 
     pss = memtrack_proc_other_pss(p);
     if (pss < 0) {
-        ALOGW("failed to get other pss: %d", pss);
+        ALOGW("failed to get other pss: %zd", pss);
         return pss;
     }
     graphics_mem->other = pss / 1024;
@@ -231,9 +231,9 @@
     unsigned referenced = 0;
     unsigned temp;
 
-    unsigned long int start;
-    unsigned long int end = 0;
-    unsigned long int prevEnd = 0;
+    uint64_t start;
+    uint64_t end = 0;
+    uint64_t prevEnd = 0;
     char* name;
     int name_pos;
 
@@ -255,7 +255,7 @@
         if (len < 1) return;
         line[--len] = 0;
 
-        if (sscanf(line, "%lx-%lx %*s %*x %*x:%*x %*d%n", &start, &end, &name_pos) != 2) {
+        if (sscanf(line, "%" SCNx64 "-%" SCNx64 " %*s %*x %*x:%*x %*d%n", &start, &end, &name_pos) != 2) {
             skip = true;
         } else {
             while (isspace(line[name_pos])) {
@@ -371,7 +371,7 @@
                 referenced = temp;
             } else if (line[0] == 'S' && sscanf(line, "Swap: %d kB", &temp) == 1) {
                 swapped_out = temp;
-            } else if (strlen(line) > 30 && line[8] == '-' && line[17] == ' ') {
+            } else if (sscanf(line, "%" SCNx64 "-%" SCNx64 " %*s %*x %*x:%*x %*d", &start, &end) == 2) {
                 // looks like a new mapping
                 // example: "10000000-10001000 ---p 10000000 00:00 0"
                 break;
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index 8cb897e..1722138 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -327,6 +327,7 @@
 
             // Exception: If we find the gdbserver binary, return it.
             if (!strncmp(lastSlash + 1, GDBSERVER, GDBSERVER_LEN)) {
+                mLastSlash = lastSlash;
                 break;
             }
 
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index c58bf04..0cdddba 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -14,46 +14,40 @@
  * limitations under the License.
  */
 
-#include "android_runtime/AndroidRuntime.h"
+#define LOG_TAG "Zygote"
 
 // sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc
 #include <sys/mount.h>
 #include <linux/fs.h>
 
 #include <grp.h>
+#include <fcntl.h>
 #include <paths.h>
 #include <signal.h>
 #include <stdlib.h>
-#include <sys/resource.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
 #include <unistd.h>
-#include <fcntl.h>
+#include <sys/capability.h>
+#include <sys/personality.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <sys/wait.h>
 
-#include "cutils/fs.h"
-#include "cutils/multiuser.h"
-#include "cutils/sched_policy.h"
-#include "utils/String8.h"
+
+#include <cutils/fs.h>
+#include <cutils/multiuser.h>
+#include <cutils/sched_policy.h>
+#include <utils/String8.h>
+#include <selinux/android.h>
+
+#include "android_runtime/AndroidRuntime.h"
 #include "JNIHelp.h"
 #include "ScopedLocalRef.h"
 #include "ScopedPrimitiveArray.h"
 #include "ScopedUtfChars.h"
 
-#if defined(HAVE_PRCTL)
-#include <sys/prctl.h>
-#endif
-
-#include <selinux/android.h>
-
-#if defined(__linux__)
-#include <sys/personality.h>
-#include <sys/utsname.h>
-#if defined(HAVE_ANDROID_OS)
-#include <sys/capability.h>
-#endif
-#endif
-
 namespace {
 
 using android::String8;
@@ -97,11 +91,9 @@
       if (WTERMSIG(status) != SIGKILL) {
         ALOGI("Process %d exited due to signal (%d)", pid, WTERMSIG(status));
       }
-#ifdef WCOREDUMP
       if (WCOREDUMP(status)) {
         ALOGI("Process %d dumped core.", pid);
       }
-#endif /* ifdef WCOREDUMP */
     }
 
     // If the just-crashed process is the system_server, bring down zygote
@@ -199,8 +191,6 @@
   }
 }
 
-#if defined(HAVE_ANDROID_OS)
-
 // The debug malloc library needs to know whether it's the zygote or a child.
 extern "C" int gMallocLeakZygoteChild;
 
@@ -254,17 +244,6 @@
   }
 }
 
-#else
-
-static int gMallocLeakZygoteChild = 0;
-
-static void EnableKeepCapabilities(JNIEnv*) {}
-static void DropCapabilitiesBoundingSet(JNIEnv*) {}
-static void SetCapabilities(JNIEnv*, int64_t, int64_t) {}
-static void SetSchedulerPolicy(JNIEnv*) {}
-
-#endif
-
 // Create a private mount namespace and bind mount appropriate emulated
 // storage for the given user.
 static bool MountEmulatedStorage(uid_t uid, jint mount_mode) {
@@ -337,7 +316,6 @@
   return true;
 }
 
-#if defined(__linux__)
 static bool NeedsNoRandomizeWorkaround() {
 #if !defined(__arm__)
     return false;
@@ -357,7 +335,6 @@
     return (major < 3) || ((major == 3) && (minor < 4));
 #endif
 }
-#endif
 
 // Utility to close down the Zygote socket file descriptors while
 // the child is still running as root with Zygote's privileges.  Each
@@ -474,7 +451,6 @@
       RuntimeAbort(env);
     }
 
-#if defined(__linux__)
     if (NeedsNoRandomizeWorkaround()) {
         // Work around ARM kernel ASLR lossage (http://b/5817320).
         int old_personality = personality(0xffffffff);
@@ -483,58 +459,49 @@
             ALOGW("personality(%d) failed", new_personality);
         }
     }
-#endif
 
     SetCapabilities(env, permittedCapabilities, effectiveCapabilities);
 
     SetSchedulerPolicy(env);
 
-#if defined(HAVE_ANDROID_OS)
-    {  // NOLINT(whitespace/braces)
-      const char* se_info_c_str = NULL;
-      ScopedUtfChars* se_info = NULL;
-      if (java_se_info != NULL) {
-          se_info = new ScopedUtfChars(env, java_se_info);
-          se_info_c_str = se_info->c_str();
-          if (se_info_c_str == NULL) {
-            ALOGE("se_info_c_str == NULL");
-            RuntimeAbort(env);
-          }
-      }
-      const char* se_name_c_str = NULL;
-      ScopedUtfChars* se_name = NULL;
-      if (java_se_name != NULL) {
-          se_name = new ScopedUtfChars(env, java_se_name);
-          se_name_c_str = se_name->c_str();
-          if (se_name_c_str == NULL) {
-            ALOGE("se_name_c_str == NULL");
-            RuntimeAbort(env);
-          }
-      }
-      rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
-      if (rc == -1) {
-        ALOGE("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
-              is_system_server, se_info_c_str, se_name_c_str);
-        RuntimeAbort(env);
-      }
-
-      // Make it easier to debug audit logs by setting the main thread's name to the
-      // nice name rather than "app_process".
-      if (se_info_c_str == NULL && is_system_server) {
-        se_name_c_str = "system_server";
-      }
-      if (se_info_c_str != NULL) {
-        SetThreadName(se_name_c_str);
-      }
-
-      delete se_info;
-      delete se_name;
+    const char* se_info_c_str = NULL;
+    ScopedUtfChars* se_info = NULL;
+    if (java_se_info != NULL) {
+        se_info = new ScopedUtfChars(env, java_se_info);
+        se_info_c_str = se_info->c_str();
+        if (se_info_c_str == NULL) {
+          ALOGE("se_info_c_str == NULL");
+          RuntimeAbort(env);
+        }
     }
-#else
-    UNUSED(is_system_server);
-    UNUSED(java_se_info);
-    UNUSED(java_se_name);
-#endif
+    const char* se_name_c_str = NULL;
+    ScopedUtfChars* se_name = NULL;
+    if (java_se_name != NULL) {
+        se_name = new ScopedUtfChars(env, java_se_name);
+        se_name_c_str = se_name->c_str();
+        if (se_name_c_str == NULL) {
+          ALOGE("se_name_c_str == NULL");
+          RuntimeAbort(env);
+        }
+    }
+    rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
+    if (rc == -1) {
+      ALOGE("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
+            is_system_server, se_info_c_str, se_name_c_str);
+      RuntimeAbort(env);
+    }
+
+    // Make it easier to debug audit logs by setting the main thread's name to the
+    // nice name rather than "app_process".
+    if (se_info_c_str == NULL && is_system_server) {
+      se_name_c_str = "system_server";
+    }
+    if (se_info_c_str != NULL) {
+      SetThreadName(se_name_c_str);
+    }
+
+    delete se_info;
+    delete se_name;
 
     UnsetSigChldHandler();
 
diff --git a/core/res/res/values-mcc214-mnc07/config.xml b/core/res/res/values-mcc214-mnc07/config.xml
new file mode 100644
index 0000000..ce7526c
--- /dev/null
+++ b/core/res/res/values-mcc214-mnc07/config.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Array of ConnectivityManager.TYPE_xxxx values allowable for tethering -->
+    <!-- Common options are [1, 4] for TYPE_WIFI and TYPE_MOBILE_DUN or
+    <!== [0,1,5,7] for TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI and TYPE_BLUETOOTH -->
+    <integer-array translatable="false" name="config_tether_upstream_types">
+      <item>1</item>
+      <item>4</item>
+      <item>7</item>
+      <item>9</item>
+    </integer-array>
+
+    <!-- String containing the apn value for tethering.  May be overriden by secure settings
+         TETHER_DUN_APN.  Value is a comma separated series of strings:
+         "name,apn,proxy,port,username,password,server,mmsc,mmsproxy,mmsport,mcc,mnc,auth,type"
+         note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
+    <string translatable="false" name="config_tether_apndata">Conexion Compartida,movistar.es,,,MOVISTAR,MOVISTAR,,,,,214,07,1,DUN</string>
+
+</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 538003f..cc2a298 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1387,7 +1387,7 @@
     <string name="permlab_accessLocationExtraCommands">access extra location provider commands</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_accessLocationExtraCommands">Allows the app to access
-      extra location provider commands.  This may allow the app to to interfere
+      extra location provider commands.  This may allow the app to interfere
       with the operation of the GPS or other location sources.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/docs/html/guide/topics/connectivity/nfc/nfc.jd b/docs/html/guide/topics/connectivity/nfc/nfc.jd
index 5011872..19ce4d7 100644
--- a/docs/html/guide/topics/connectivity/nfc/nfc.jd
+++ b/docs/html/guide/topics/connectivity/nfc/nfc.jd
@@ -477,7 +477,7 @@
   <li>{@link android.nfc.NfcAdapter#EXTRA_TAG} (required): A {@link android.nfc.Tag} object
 representing the scanned tag.</li>
   <li>{@link android.nfc.NfcAdapter#EXTRA_NDEF_MESSAGES} (optional): An array of NDEF messages
-parsed from the tag. This extra is mandatory on {@link android.nfc.NfcAdapter#ACTION_NDEF_DISCOVERED
+parsed from the tag. This extra is mandatory on {@link android.nfc.NfcAdapter#ACTION_NDEF_DISCOVERED}
 intents.</li>
   <li>{@link android.nfc.NfcAdapter#EXTRA_ID} (optional): The low-level ID of the tag.</li></ul>
 
diff --git a/docs/html/guide/topics/manifest/application-element.jd b/docs/html/guide/topics/manifest/application-element.jd
index 28deed9..33f6bce 100644
--- a/docs/html/guide/topics/manifest/application-element.jd
+++ b/docs/html/guide/topics/manifest/application-element.jd
@@ -81,7 +81,7 @@
 </p></dd>
 
 
-<dt><a name="allowbackup"></a>{@code android:allowbackup}</dt>
+<dt><a name="allowbackup"></a>{@code android:allowBackup}</dt>
 <dd>Whether to allow the application to participate in the backup
 and restore infrastructure. If this attribute is set to false, no backup
 or restore of the application will ever be performed, even by a full-system
diff --git a/docs/html/guide/topics/ui/layout/relative.jd b/docs/html/guide/topics/ui/layout/relative.jd
index 65c5617..1acb2e3 100644
--- a/docs/html/guide/topics/ui/layout/relative.jd
+++ b/docs/html/guide/topics/ui/layout/relative.jd
@@ -20,7 +20,7 @@
 <p>{@link android.widget.RelativeLayout} is a view group that displays child views in relative
 positions. The position of each view can be specified as relative to sibling elements (such as to
 the left-of or below another view) or in positions relative to the parent {@link
-android.widget.RelativeLayout} area (such as aligned to the bottom, left of center).</p>
+android.widget.RelativeLayout} area (such as aligned to the bottom, left or center).</p>
 
 <img src="{@docRoot}images/ui/relativelayout.png" alt="" />
 
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 67e8f23..db2ad9d 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -472,7 +472,7 @@
 
     /**
      * Synonym for {@link #decodeResource(Resources, int, android.graphics.BitmapFactory.Options)}
-     * will null Options.
+     * with null Options.
      *
      * @param res The resources object containing the image data
      * @param id The resource id of the image data
diff --git a/graphics/java/android/graphics/PathMeasure.java b/graphics/java/android/graphics/PathMeasure.java
index e56716f..91b092a 100644
--- a/graphics/java/android/graphics/PathMeasure.java
+++ b/graphics/java/android/graphics/PathMeasure.java
@@ -35,7 +35,7 @@
     
     /**
      * Create a PathMeasure object associated with the specified path object
-     * (already created and specified). The meansure object can now return the
+     * (already created and specified). The measure object can now return the
      * path's length, and the position and tangent of any position along the
      * path.
      *
diff --git a/include/android_runtime/AndroidRuntime.h b/include/android_runtime/AndroidRuntime.h
index 3dfdb46..45aa745 100644
--- a/include/android_runtime/AndroidRuntime.h
+++ b/include/android_runtime/AndroidRuntime.h
@@ -116,6 +116,14 @@
 
 private:
     static int startReg(JNIEnv* env);
+    bool parseRuntimeOption(const char* property,
+                            char* buffer,
+                            const char* runtimeArg,
+                            const char* defaultArg = "");
+    bool parseCompilerRuntimeOption(const char* property,
+                                    char* buffer,
+                                    const char* runtimeArg,
+                                    const char* quotingArg);
     void parseExtraOpts(char* extraOptsBuf, const char* quotingArg);
     int startVm(JavaVM** pJavaVM, JNIEnv** pEnv);
 
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index b4d482a..56c95bd 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -347,6 +347,15 @@
     setLocaleLocked(locale);
 }
 
+
+static const char kFilPrefix[] = "fil";
+static const char kTlPrefix[] = "tl";
+
+// The sizes of the prefixes, excluding the 0 suffix.
+// char.
+static const int kFilPrefixLen = sizeof(kFilPrefix) - 1;
+static const int kTlPrefixLen = sizeof(kTlPrefix) - 1;
+
 void AssetManager::setLocaleLocked(const char* locale)
 {
     if (mLocale != NULL) {
@@ -355,8 +364,46 @@
         //mZipSet.purgeLocale();
         delete[] mLocale;
     }
-    mLocale = strdupNew(locale);
 
+    // If we're attempting to set a locale that starts with "fil",
+    // we should convert it to "tl" for backwards compatibility since
+    // we've been using "tl" instead of "fil" prior to L.
+    //
+    // If the resource table already has entries for "fil", we use that
+    // instead of attempting a fallback.
+    if (strncmp(locale, kFilPrefix, kFilPrefixLen) == 0) {
+        Vector<String8> locales;
+        ResTable* res = mResources;
+        if (res != NULL) {
+            res->getLocales(&locales);
+        }
+        const size_t localesSize = locales.size();
+        bool hasFil = false;
+        for (size_t i = 0; i < localesSize; ++i) {
+            if (locales[i].find(kFilPrefix) == 0) {
+                hasFil = true;
+                break;
+            }
+        }
+
+
+        if (!hasFil) {
+            const size_t newLocaleLen = strlen(locale);
+            // This isn't a bug. We really do want mLocale to be 1 byte
+            // shorter than locale, because we're replacing "fil-" with
+            // "tl-".
+            mLocale = new char[newLocaleLen];
+            // Copy over "tl".
+            memcpy(mLocale, kTlPrefix, kTlPrefixLen);
+            // Copy the rest of |locale|, including the terminating '\0'.
+            memcpy(mLocale + kTlPrefixLen, locale + kFilPrefixLen,
+                   newLocaleLen - kFilPrefixLen + 1);
+            updateResourceParamsLocked();
+            return;
+        }
+    }
+
+    mLocale = strdupNew(locale);
     updateResourceParamsLocked();
 }
 
@@ -741,6 +788,16 @@
     if (res != NULL) {
         res->getLocales(locales);
     }
+
+    const size_t numLocales = locales->size();
+    for (size_t i = 0; i < numLocales; ++i) {
+        const String8& localeStr = locales->itemAt(i);
+        if (localeStr.find(kTlPrefix) == 0) {
+            String8 replaced("fil");
+            replaced += (localeStr.string() + kTlPrefixLen);
+            locales->editItemAt(i) = replaced;
+        }
+    }
 }
 
 /*
@@ -1747,6 +1804,7 @@
     }
 
     mergeInfoLocked(pMergedInfo, pContents);
+    delete pContents;
     return true;
 }
 
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 1ffe665..2f3b1f7 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -1597,9 +1597,9 @@
       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;
+      uint8_t first = (in[0] - base) & 0x007f;
+      uint8_t second = (in[1] - base) & 0x007f;
+      uint8_t third = (in[2] - base) & 0x007f;
 
       out[0] = (0x80 | (third << 2) | (second >> 3));
       out[1] = ((second << 5) | first);
@@ -5405,23 +5405,33 @@
                 return (mError=err);
             }
 
-            //printf("Adding new package id %d at index %d\n", id, idx);
-            err = mPackageGroups.add(group);
+            err = group->packages.add(package);
             if (err < NO_ERROR) {
+                delete group;
+                delete package;
                 return (mError=err);
             }
             group->basePackage = package;
 
+            //printf("Adding new package id %d at index %d\n", id, idx);
+            err = mPackageGroups.add(group);
+            if (err < NO_ERROR) {
+                delete group;
+                return (mError=err);
+            }
+
             mPackageMap[id] = (uint8_t)idx;
         } else {
             group = mPackageGroups.itemAt(idx-1);
             if (group == NULL) {
+                delete package;
                 return (mError=UNKNOWN_ERROR);
             }
-        }
-        err = group->packages.add(package);
-        if (err < NO_ERROR) {
-            return (mError=err);
+            err = group->packages.add(package);
+            if (err < NO_ERROR) {
+                delete package;
+                return (mError=err);
+            }
         }
     } else {
         LOG_ALWAYS_FATAL("Package id out of range");
diff --git a/libs/androidfw/tests/ResourceTypes_test.cpp b/libs/androidfw/tests/ResourceTypes_test.cpp
index 4888b4a..139f868 100644
--- a/libs/androidfw/tests/ResourceTypes_test.cpp
+++ b/libs/androidfw/tests/ResourceTypes_test.cpp
@@ -75,6 +75,30 @@
      EXPECT_EQ(0, out[3]);
 }
 
+TEST(ResourceTypesTest, ResourceConfig_packAndUnpack3LetterLanguageAtOffset16) {
+     ResTable_config config;
+     config.packLanguage("tgp");
+
+     // We had a bug where we would accidentally mask
+     // the 5th bit of both bytes
+     //
+     // packed[0] = 1011 1100
+     // packed[1] = 1101 0011
+     //
+     // which is equivalent to:
+     // 1  [0]   [1]   [2]
+     // 1-01111-00110-10011
+     EXPECT_EQ(0xbc, config.language[0]);
+     EXPECT_EQ(0xd3, config.language[1]);
+
+     char out[4] = { 1, 1, 1, 1};
+     config.unpackLanguage(out);
+     EXPECT_EQ('t', out[0]);
+     EXPECT_EQ('g', out[1]);
+     EXPECT_EQ('p', out[2]);
+     EXPECT_EQ(0, out[3]);
+}
+
 TEST(ResourceTypesTest, ResourceConfig_packAndUnpack3LetterRegion) {
      ResTable_config config;
      config.packRegion("419");
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index f8d3589..b0f4c2c 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -554,11 +554,8 @@
     // call, any texture operation will be performed on the default
     // texture (name=0)
 
-    for (int i = 0; i < REQUIRED_TEXTURE_UNITS_COUNT; i++) {
-        if (mBoundTextures[i] == texture) {
-            mBoundTextures[i] = 0;
-        }
-    }
+    unbindTexture(texture);
+
     glDeleteTextures(1, &texture);
 }
 
@@ -566,6 +563,14 @@
     memset(mBoundTextures, 0, REQUIRED_TEXTURE_UNITS_COUNT * sizeof(GLuint));
 }
 
+void Caches::unbindTexture(GLuint texture) {
+    for (int i = 0; i < REQUIRED_TEXTURE_UNITS_COUNT; i++) {
+        if (mBoundTextures[i] == texture) {
+            mBoundTextures[i] = 0;
+        }
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // Scissor
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 282aee9..544757a 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -264,6 +264,11 @@
     void resetBoundTextures();
 
     /**
+     * Clear the cache of bound textures.
+     */
+    void unbindTexture(GLuint texture);
+
+    /**
      * Sets the scissor for the current surface.
      */
     bool setScissor(GLint x, GLint y, GLint width, GLint height);
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index bd371a3..987bf03 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -171,6 +171,7 @@
 }
 
 void Layer::clearTexture() {
+    caches.unbindTexture(texture.id);
     texture.id = 0;
 }
 
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index f8076cc..006d145 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -339,8 +339,10 @@
 
 void LayerRenderer::flushLayer(Layer* layer) {
 #ifdef GL_EXT_discard_framebuffer
+    if (!layer) return;
+
     GLuint fbo = layer->getFbo();
-    if (layer && fbo) {
+    if (fbo) {
         // If possible, discard any enqueud operations on deferred
         // rendering architectures
         if (Extensions::getInstance().hasDiscardFramebuffer()) {
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index d5ba8c3..2f102e0 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -242,19 +242,19 @@
     switch (bitmap->getConfig()) {
     case SkBitmap::kA8_Config:
         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-        uploadToTexture(resize, GL_ALPHA, bitmap->rowBytesAsPixels(),
+        uploadToTexture(resize, GL_ALPHA, bitmap->rowBytesAsPixels(), bitmap->bytesPerPixel(),
                 texture->width, texture->height, GL_UNSIGNED_BYTE, bitmap->getPixels());
         texture->blend = true;
         break;
     case SkBitmap::kRGB_565_Config:
         glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel());
-        uploadToTexture(resize, GL_RGB, bitmap->rowBytesAsPixels(),
+        uploadToTexture(resize, GL_RGB, bitmap->rowBytesAsPixels(), bitmap->bytesPerPixel(),
                 texture->width, texture->height, GL_UNSIGNED_SHORT_5_6_5, bitmap->getPixels());
         texture->blend = false;
         break;
     case SkBitmap::kARGB_8888_Config:
         glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel());
-        uploadToTexture(resize, GL_RGBA, bitmap->rowBytesAsPixels(),
+        uploadToTexture(resize, GL_RGBA, bitmap->rowBytesAsPixels(), bitmap->bytesPerPixel(),
                 texture->width, texture->height, GL_UNSIGNED_BYTE, bitmap->getPixels());
         // Do this after calling getPixels() to make sure Skia's deferred
         // decoding happened
@@ -294,27 +294,49 @@
     SkCanvas canvas(rgbaBitmap);
     canvas.drawBitmap(*bitmap, 0.0f, 0.0f, NULL);
 
-    uploadToTexture(resize, GL_RGBA, rgbaBitmap.rowBytesAsPixels(), width, height,
-            GL_UNSIGNED_BYTE, rgbaBitmap.getPixels());
+    uploadToTexture(resize, GL_RGBA, rgbaBitmap.rowBytesAsPixels(), rgbaBitmap.bytesPerPixel(),
+            width, height, GL_UNSIGNED_BYTE, rgbaBitmap.getPixels());
 }
 
-void TextureCache::uploadToTexture(bool resize, GLenum format, GLsizei stride,
+void TextureCache::uploadToTexture(bool resize, GLenum format, GLsizei stride, GLsizei bpp,
         GLsizei width, GLsizei height, GLenum type, const GLvoid * data) {
-    // TODO: With OpenGL ES 2.0 we need to copy the bitmap in a temporary buffer
-    //       if the stride doesn't match the width
     const bool useStride = stride != width && Extensions::getInstance().hasUnpackRowLength();
-    if (useStride) {
-        glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
-    }
+    if ((stride == width) || useStride) {
+        if (useStride) {
+            glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
+        }
 
-    if (resize) {
-        glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, data);
+        if (resize) {
+            glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, data);
+        } else {
+            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, data);
+        }
+
+        if (useStride) {
+            glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+        }
     } else {
-        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, data);
-    }
+        //  With OpenGL ES 2.0 we need to copy the bitmap in a temporary buffer
+        //  if the stride doesn't match the width
 
-    if (useStride) {
-        glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+        GLvoid * temp = (GLvoid *) malloc(width * height * bpp);
+        if (!temp) return;
+
+        uint8_t * pDst = (uint8_t *)temp;
+        uint8_t * pSrc = (uint8_t *)data;
+        for (GLsizei i = 0; i < height; i++) {
+            memcpy(pDst, pSrc, width * bpp);
+            pDst += width * bpp;
+            pSrc += stride * bpp;
+        }
+
+        if (resize) {
+            glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, temp);
+        } else {
+            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, temp);
+        }
+
+        free(temp);
     }
 }
 
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index 57fc19a..909d762 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -125,7 +125,7 @@
     void generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate = false);
 
     void uploadLoFiTexture(bool resize, SkBitmap* bitmap, uint32_t width, uint32_t height);
-    void uploadToTexture(bool resize, GLenum format, GLsizei stride,
+    void uploadToTexture(bool resize, GLenum format, GLsizei stride, GLsizei bpp,
             GLsizei width, GLsizei height, GLenum type, const GLvoid * data);
 
     void init();
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index ccb4304..170ec98 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1642,7 +1642,7 @@
         }
         if (!intent.isTargetedToPackage()) {
             IllegalArgumentException e = new IllegalArgumentException(
-                    "pending intent msut be targeted to package");
+                    "pending intent must be targeted to package");
             if (mContext.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.JELLY_BEAN) {
                 throw e;
             } else {
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 06a8f4c..4599bd6 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -1184,6 +1184,7 @@
         HashSet<String> existingFiles = new HashSet<String>();
         String directory = "/sdcard/DCIM/.thumbnails";
         String [] files = (new File(directory)).list();
+        Cursor c = null;
         if (files == null)
             files = new String[0];
 
@@ -1193,7 +1194,7 @@
         }
 
         try {
-            Cursor c = mMediaProvider.query(
+            c = mMediaProvider.query(
                     mPackageName,
                     mThumbsUri,
                     new String [] { "_data" },
@@ -1218,11 +1219,12 @@
             }
 
             Log.v(TAG, "/pruneDeadThumbnailFiles... " + c);
+        } catch (RemoteException e) {
+            // We will soon be killed...
+        } finally {
             if (c != null) {
                 c.close();
             }
-        } catch (RemoteException e) {
-            // We will soon be killed...
         }
     }
 
diff --git a/media/java/android/media/MiniThumbFile.java b/media/java/android/media/MiniThumbFile.java
index 63b149c..6364300 100644
--- a/media/java/android/media/MiniThumbFile.java
+++ b/media/java/android/media/MiniThumbFile.java
@@ -249,7 +249,8 @@
                 long magic = mBuffer.getLong();
                 int length = mBuffer.getInt();
 
-                if (size >= 1 + 8 + 4 + length && data.length >= length) {
+                if (size >= 1 + 8 + 4 + length && length != 0 && magic != 0 && flag == 1 &&
+                        data.length >= length) {
                     mBuffer.get(data, 0, length);
                     return data;
                 }
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index c2694f1..0e34789 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -23,6 +23,7 @@
 #include <utils/threads.h>
 #include <core/SkBitmap.h>
 #include <media/mediametadataretriever.h>
+#include <media/mediascanner.h>
 #include <private/media/VideoFrame.h>
 
 #include "jni.h"
@@ -326,17 +327,13 @@
         return NULL;
     }
 
-    unsigned int len = mediaAlbumArt->mSize;
-    char* data = (char*) mediaAlbumArt + sizeof(MediaAlbumArt);
-    jbyteArray array = env->NewByteArray(len);
+    jbyteArray array = env->NewByteArray(mediaAlbumArt->size());
     if (!array) {  // OutOfMemoryError exception has already been thrown.
         ALOGE("getEmbeddedPicture: OutOfMemoryError is thrown.");
     } else {
-        jbyte* bytes = env->GetByteArrayElements(array, NULL);
-        if (bytes != NULL) {
-            memcpy(bytes, data, len);
-            env->ReleaseByteArrayElements(array, bytes, 0);
-        }
+        const jbyte* data =
+                reinterpret_cast<const jbyte*>(mediaAlbumArt->data());
+        env->SetByteArrayRegion(array, 0, mediaAlbumArt->size(), data);
     }
 
     // No need to delete mediaAlbumArt here
diff --git a/media/jni/android_media_MediaScanner.cpp b/media/jni/android_media_MediaScanner.cpp
index b520440..321c2e3 100644
--- a/media/jni/android_media_MediaScanner.cpp
+++ b/media/jni/android_media_MediaScanner.cpp
@@ -348,17 +348,16 @@
     }
 
     int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    MediaAlbumArt* mediaAlbumArt =
-            reinterpret_cast<MediaAlbumArt*>(mp->extractAlbumArt(fd));
+    MediaAlbumArt* mediaAlbumArt = mp->extractAlbumArt(fd);
     if (mediaAlbumArt == NULL) {
         return NULL;
     }
 
-    jbyteArray array = env->NewByteArray(mediaAlbumArt->mSize);
+    jbyteArray array = env->NewByteArray(mediaAlbumArt->size());
     if (array != NULL) {
-        jbyte* bytes = env->GetByteArrayElements(array, NULL);
-        memcpy(bytes, &mediaAlbumArt->mData[0], mediaAlbumArt->mSize);
-        env->ReleaseByteArrayElements(array, bytes, 0);
+        const jbyte* data =
+                reinterpret_cast<const jbyte*>(mediaAlbumArt->data());
+        env->SetByteArrayRegion(array, 0, mediaAlbumArt->size(), data);
     }
 
 done:
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index ec87c6e..16a0d35 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -49,6 +49,7 @@
 
 import com.android.internal.app.IMediaContainerService;
 import com.android.internal.content.NativeLibraryHelper;
+import com.android.internal.content.NativeLibraryHelper.ApkHandle;
 import com.android.internal.content.PackageHelper;
 
 import java.io.BufferedInputStream;
@@ -106,8 +107,27 @@
                 return null;
             }
 
-            return copyResourceInner(packageURI, cid, key, resFileName, publicResFileName,
-                    isExternal, isForwardLocked, abiOverride);
+
+            if (isExternal) {
+                // Make sure the sdcard is mounted.
+                String status = Environment.getExternalStorageState();
+                if (!status.equals(Environment.MEDIA_MOUNTED)) {
+                    Slog.w(TAG, "Make sure sdcard is mounted.");
+                    return null;
+                }
+            }
+
+            ApkHandle handle = null;
+            try {
+                handle = ApkHandle.create(packageURI.getPath());
+                return copyResourceInner(packageURI, cid, key, resFileName, publicResFileName,
+                        isExternal, isForwardLocked, handle, abiOverride);
+            } catch (IOException ioe) {
+                Slog.w(TAG, "Problem opening APK: " + packageURI.getPath());
+                return null;
+            } finally {
+                IoUtils.closeQuietly(handle);
+            }
         }
 
         /**
@@ -328,21 +348,11 @@
 
     private String copyResourceInner(Uri packageURI, String newCid, String key, String resFileName,
             String publicResFileName, boolean isExternal, boolean isForwardLocked,
-            String abiOverride) {
-
-        if (isExternal) {
-            // Make sure the sdcard is mounted.
-            String status = Environment.getExternalStorageState();
-            if (!status.equals(Environment.MEDIA_MOUNTED)) {
-                Slog.w(TAG, "Make sure sdcard is mounted.");
-                return null;
-            }
-        }
-
+            ApkHandle handle, String abiOverride) {
         // The .apk file
         String codePath = packageURI.getPath();
         File codeFile = new File(codePath);
-        NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(codePath);
+
         String[] abiList = Build.SUPPORTED_ABIS;
         if (abiOverride != null) {
             abiList = new String[] { abiOverride };
@@ -849,14 +859,14 @@
 
     private int calculateContainerSize(File apkFile, boolean forwardLocked,
             String abiOverride) throws IOException {
-        NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(apkFile);
-        final int abi = NativeLibraryHelper.findSupportedAbi(handle,
-                (abiOverride != null) ? new String[] { abiOverride } : Build.SUPPORTED_ABIS);
-
+        ApkHandle handle = null;
         try {
+            handle = ApkHandle.create(apkFile);
+            final int abi = NativeLibraryHelper.findSupportedAbi(handle,
+                    (abiOverride != null) ? new String[] { abiOverride } : Build.SUPPORTED_ABIS);
             return calculateContainerSize(handle, apkFile, abi, forwardLocked);
         } finally {
-            handle.close();
+            IoUtils.closeQuietly(handle);
         }
     }
 
diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java
index c2bab91..20b7ee7 100644
--- a/rs/java/android/renderscript/Allocation.java
+++ b/rs/java/android/renderscript/Allocation.java
@@ -776,10 +776,11 @@
         mRS.validate();
         int eSize = mType.mElement.getBytesSize();
         final byte[] data = fp.getData();
+        int data_length = fp.getPos();
 
-        int count = data.length / eSize;
-        if ((eSize * count) != data.length) {
-            throw new RSIllegalArgumentException("Field packer length " + data.length +
+        int count = data_length / eSize;
+        if ((eSize * count) != data_length) {
+            throw new RSIllegalArgumentException("Field packer length " + data_length +
                                                " not divisible by element size " + eSize + ".");
         }
         copy1DRangeFromUnchecked(xoff, count, data);
@@ -803,16 +804,17 @@
         }
 
         final byte[] data = fp.getData();
+        int data_length = fp.getPos();
         int eSize = mType.mElement.mElements[component_number].getBytesSize();
         eSize *= mType.mElement.mArraySizes[component_number];
 
-        if (data.length != eSize) {
-            throw new RSIllegalArgumentException("Field packer sizelength " + data.length +
+        if (data_length != eSize) {
+            throw new RSIllegalArgumentException("Field packer sizelength " + data_length +
                                                " does not match component size " + eSize + ".");
         }
 
         mRS.nAllocationElementData1D(getIDSafe(), xoff, mSelectedLOD,
-                                     component_number, data, data.length);
+                                     component_number, data, data_length);
     }
 
     private void data1DChecks(int off, int count, int len, int dataSize) {
diff --git a/rs/java/android/renderscript/Element.java b/rs/java/android/renderscript/Element.java
index aa5d687..f2f1c86 100644
--- a/rs/java/android/renderscript/Element.java
+++ b/rs/java/android/renderscript/Element.java
@@ -143,17 +143,17 @@
         MATRIX_3X3 (17, 36),
         MATRIX_2X2 (18, 16),
 
-        RS_ELEMENT (1000, 4),
-        RS_TYPE (1001, 4),
-        RS_ALLOCATION (1002, 4),
-        RS_SAMPLER (1003, 4),
-        RS_SCRIPT (1004, 4),
-        RS_MESH (1005, 4),
-        RS_PROGRAM_FRAGMENT (1006, 4),
-        RS_PROGRAM_VERTEX (1007, 4),
-        RS_PROGRAM_RASTER (1008, 4),
-        RS_PROGRAM_STORE (1009, 4),
-        RS_FONT (1010, 4);
+        RS_ELEMENT (1000),
+        RS_TYPE (1001),
+        RS_ALLOCATION (1002),
+        RS_SAMPLER (1003),
+        RS_SCRIPT (1004),
+        RS_MESH (1005),
+        RS_PROGRAM_FRAGMENT (1006),
+        RS_PROGRAM_VERTEX (1007),
+        RS_PROGRAM_RASTER (1008),
+        RS_PROGRAM_STORE (1009),
+        RS_FONT (1010);
 
         int mID;
         int mSize;
@@ -161,6 +161,14 @@
             mID = id;
             mSize = size;
         }
+
+        DataType(int id) {
+            mID = id;
+            mSize = 4;
+            if (RenderScript.sPointerSize == 8) {
+                mSize = 32;
+            }
+        }
     }
 
     /**
diff --git a/rs/java/android/renderscript/FieldPacker.java b/rs/java/android/renderscript/FieldPacker.java
index 2ff1c28..9048c31 100644
--- a/rs/java/android/renderscript/FieldPacker.java
+++ b/rs/java/android/renderscript/FieldPacker.java
@@ -37,10 +37,15 @@
     }
 
     public FieldPacker(byte[] data) {
-        mPos = 0;
+        // Advance mPos to the end of the buffer, since we are copying in the
+        // full data input.
+        mPos = data.length;
         mLen = data.length;
         mData = data;
         mAlignment = new BitSet();
+        // TODO: We should either have an actual FieldPacker copy constructor
+        // or drop support for computing alignment like this. As it stands,
+        // subAlign() can never work correctly for copied FieldPacker objects.
     }
 
     public void align(int v) {
@@ -76,7 +81,7 @@
         mPos = 0;
     }
     public void reset(int i) {
-        if ((i < 0) || (i >= mLen)) {
+        if ((i < 0) || (i > mLen)) {
             throw new RSIllegalArgumentException("out of range argument: " + i);
         }
         mPos = i;
@@ -234,6 +239,9 @@
         if (obj != null) {
             if (RenderScript.sPointerSize == 8) {
                 addI64(obj.getID(null));
+                addI64(0);
+                addI64(0);
+                addI64(0);
             }
             else {
                 addI32((int)obj.getID(null));
@@ -241,6 +249,9 @@
         } else {
             if (RenderScript.sPointerSize == 8) {
                 addI64(0);
+                addI64(0);
+                addI64(0);
+                addI64(0);
             } else {
                 addI32(0);
             }
@@ -600,6 +611,15 @@
         return mData;
     }
 
+    /**
+     * Get the actual length used for the FieldPacker.
+     *
+     * @hide
+     */
+    public int getPos() {
+        return mPos;
+    }
+
     private final byte mData[];
     private int mPos;
     private int mLen;
diff --git a/rs/java/android/renderscript/ProgramVertexFixedFunction.java b/rs/java/android/renderscript/ProgramVertexFixedFunction.java
index a350154..7026597 100644
--- a/rs/java/android/renderscript/ProgramVertexFixedFunction.java
+++ b/rs/java/android/renderscript/ProgramVertexFixedFunction.java
@@ -249,6 +249,9 @@
             for(int i = 0; i < 16; i ++) {
                 mIOBuffer.addF32(m.mMat[i]);
             }
+            // Reset the buffer back to the end, since we want to flush all of
+            // the contents back (and not just what we wrote now).
+            mIOBuffer.reset(mIOBuffer.getData().length);
             mAlloc.setFromFieldPacker(0, mIOBuffer);
         }
 
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index bbe5c49..f2b1380 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -615,6 +615,29 @@
         }
     }
 
+    /**
+     * Multi-input code.
+     *
+     */
+
+    // @hide
+    native void rsnScriptForEachMultiClipped(long con, long id, int slot, long[] ains, long aout, byte[] params,
+                                             int xstart, int xend, int ystart, int yend, int zstart, int zend);
+    // @hide
+    native void rsnScriptForEachMultiClipped(long con, long id, int slot, long[] ains, long aout,
+                                             int xstart, int xend, int ystart, int yend, int zstart, int zend);
+
+    // @hide
+    synchronized void nScriptForEachMultiClipped(long id, int slot, long[] ains, long aout, byte[] params,
+                                                 int xstart, int xend, int ystart, int yend, int zstart, int zend) {
+        validate();
+        if (params == null) {
+            rsnScriptForEachMultiClipped(mContext, id, slot, ains, aout, xstart, xend, ystart, yend, zstart, zend);
+        } else {
+            rsnScriptForEachMultiClipped(mContext, id, slot, ains, aout, params, xstart, xend, ystart, yend, zstart, zend);
+        }
+    }
+
     native void rsnScriptInvokeV(long con, long id, int slot, byte[] params);
     synchronized void nScriptInvokeV(long id, int slot, byte[] params) {
         validate();
diff --git a/rs/java/android/renderscript/Script.java b/rs/java/android/renderscript/Script.java
index 0e46f94..c49ef94 100644
--- a/rs/java/android/renderscript/Script.java
+++ b/rs/java/android/renderscript/Script.java
@@ -182,6 +182,54 @@
         mRS.nScriptForEachClipped(getID(mRS), slot, in_id, out_id, params, sc.xstart, sc.xend, sc.ystart, sc.yend, sc.zstart, sc.zend);
     }
 
+    /**
+     * Only intended for use by generated reflected code.
+     *
+     * @hide
+     */
+    protected void forEach(int slot, Allocation[] ains, Allocation aout, FieldPacker v) {
+        forEach(slot, ains, aout, v, new LaunchOptions());
+    }
+
+    /**
+     * Only intended for use by generated reflected code.
+     *
+     * @hide
+     */
+    protected void forEach(int slot, Allocation[] ains, Allocation aout, FieldPacker v, LaunchOptions sc) {
+        mRS.validate();
+
+        for (Allocation ain : ains) {
+          mRS.validateObject(ain);
+        }
+
+        mRS.validateObject(aout);
+        if (ains == null && aout == null) {
+            throw new RSIllegalArgumentException(
+                "At least one of ain or aout is required to be non-null.");
+        }
+
+        if (sc == null) {
+            forEach(slot, ains, aout, v);
+            return;
+        }
+
+        long[] in_ids = new long[ains.length];
+        for (int index = 0; index < ains.length; ++index) {
+            in_ids[index] = ains[index].getID(mRS);
+        }
+
+        long out_id = 0;
+        if (aout != null) {
+            out_id = aout.getID(mRS);
+        }
+        byte[] params = null;
+        if (v != null) {
+            params = v.getData();
+        }
+        mRS.nScriptForEachMultiClipped(getID(mRS), slot, in_ids, out_id, params, sc.xstart, sc.xend, sc.ystart, sc.yend, sc.zstart, sc.zend);
+    }
+
     Script(long id, RenderScript rs) {
         super(id, rs);
     }
@@ -477,4 +525,3 @@
 
     }
 }
-
diff --git a/rs/java/android/renderscript/ScriptIntrinsic.java b/rs/java/android/renderscript/ScriptIntrinsic.java
index 8719e017..4edce84 100644
--- a/rs/java/android/renderscript/ScriptIntrinsic.java
+++ b/rs/java/android/renderscript/ScriptIntrinsic.java
@@ -27,5 +27,8 @@
 public abstract class ScriptIntrinsic extends Script {
     ScriptIntrinsic(long id, RenderScript rs) {
         super(id, rs);
+        if (id == 0) {
+            throw new RSRuntimeException("Loading of ScriptIntrinsic failed.");
+        }
     }
 }
diff --git a/rs/java/android/renderscript/ScriptIntrinsicBlur.java b/rs/java/android/renderscript/ScriptIntrinsicBlur.java
index d1a6fed..c153712 100644
--- a/rs/java/android/renderscript/ScriptIntrinsicBlur.java
+++ b/rs/java/android/renderscript/ScriptIntrinsicBlur.java
@@ -88,7 +88,7 @@
      *             type.
      */
     public void forEach(Allocation aout) {
-        forEach(0, null, aout, null);
+        forEach(0, (Allocation) null, aout, null);
     }
 
     /**
@@ -109,4 +109,3 @@
         return createFieldID(1, null);
     }
 }
-
diff --git a/rs/java/android/renderscript/ScriptIntrinsicConvolve3x3.java b/rs/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
index 25f3ee8..586930c 100644
--- a/rs/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
+++ b/rs/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
@@ -108,7 +108,7 @@
      *             type.
      */
     public void forEach(Allocation aout) {
-        forEach(0, null, aout, null);
+        forEach(0, (Allocation) null, aout, null);
     }
 
     /**
@@ -130,4 +130,3 @@
     }
 
 }
-
diff --git a/rs/java/android/renderscript/ScriptIntrinsicConvolve5x5.java b/rs/java/android/renderscript/ScriptIntrinsicConvolve5x5.java
index 71ea4cbc..aebafc2 100644
--- a/rs/java/android/renderscript/ScriptIntrinsicConvolve5x5.java
+++ b/rs/java/android/renderscript/ScriptIntrinsicConvolve5x5.java
@@ -109,7 +109,7 @@
      *             type.
      */
     public void forEach(Allocation aout) {
-        forEach(0, null, aout, null);
+        forEach(0, (Allocation) null, aout, null);
     }
 
     /**
@@ -130,4 +130,3 @@
         return createFieldID(1, null);
     }
 }
-
diff --git a/rs/java/android/renderscript/ScriptIntrinsicResize.java b/rs/java/android/renderscript/ScriptIntrinsicResize.java
index cc37120..816029f 100644
--- a/rs/java/android/renderscript/ScriptIntrinsicResize.java
+++ b/rs/java/android/renderscript/ScriptIntrinsicResize.java
@@ -96,7 +96,7 @@
      * @param opt LaunchOptions for clipping
      */
     public void forEach_bicubic(Allocation aout, Script.LaunchOptions opt) {
-        forEach(0, null, aout, null, opt);
+        forEach(0, (Allocation) null, aout, null, opt);
     }
 
     /**
@@ -110,4 +110,3 @@
 
 
 }
-
diff --git a/rs/java/android/renderscript/ScriptIntrinsicYuvToRGB.java b/rs/java/android/renderscript/ScriptIntrinsicYuvToRGB.java
index f942982..e64c911 100644
--- a/rs/java/android/renderscript/ScriptIntrinsicYuvToRGB.java
+++ b/rs/java/android/renderscript/ScriptIntrinsicYuvToRGB.java
@@ -66,7 +66,7 @@
      *             type.
      */
     public void forEach(Allocation aout) {
-        forEach(0, null, aout, null);
+        forEach(0, (Allocation) null, aout, null);
     }
 
     /**
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index af2e3bf..7133a21 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -1054,7 +1054,7 @@
     jint dimsLen = _env->GetArrayLength(dims) * sizeof(int);
     jint *dimsPtr = _env->GetIntArrayElements(dims, NULL);
     rsScriptSetVarVE((RsContext)con, (RsScript)script, slot, ptr, len, (RsElement)elem,
-                     (const size_t*) dimsPtr, dimsLen);
+                     (const uint32_t*) dimsPtr, dimsLen);
     _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
     _env->ReleaseIntArrayElements(dims, dimsPtr, JNI_ABORT);
 }
@@ -1154,6 +1154,101 @@
     _env->ReleaseByteArrayElements(params, ptr, JNI_ABORT);
 }
 
+static void
+nScriptForEachMultiClipped(JNIEnv *_env, jobject _this, jlong con,
+                      jlong script, jint slot, jlongArray ains, jlong aout,
+                      jint xstart, jint xend,
+                      jint ystart, jint yend, jint zstart, jint zend)
+{
+    LOG_API("nScriptForEachMultiClipped, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
+
+    jint   in_len = _env->GetArrayLength(ains);
+    jlong* in_ptr = _env->GetLongArrayElements(ains, NULL);
+
+    RsAllocation *in_allocs = NULL;
+
+    if (sizeof(RsAllocation) == sizeof(jlong)) {
+      in_allocs = (RsAllocation*)in_ptr;
+
+    } else {
+      // Convert from 64-bit jlong types to the native pointer type.
+
+      in_allocs = new RsAllocation[in_len];
+
+      for (int index = in_len; --index >= 0;) {
+        in_allocs[index] = (RsAllocation)in_ptr[index];
+      }
+    }
+
+    RsScriptCall sc;
+    sc.xStart = xstart;
+    sc.xEnd = xend;
+    sc.yStart = ystart;
+    sc.yEnd = yend;
+    sc.zStart = zstart;
+    sc.zEnd = zend;
+    sc.strategy = RS_FOR_EACH_STRATEGY_DONT_CARE;
+    sc.arrayStart = 0;
+    sc.arrayEnd = 0;
+
+    rsScriptForEachMulti((RsContext)con, (RsScript)script, slot, in_allocs, in_len, (RsAllocation)aout, NULL, 0, &sc, sizeof(sc));
+
+    if (sizeof(RsAllocation) != sizeof(jlong)) {
+      delete[] in_allocs;
+    }
+
+    _env->ReleaseLongArrayElements(ains, in_ptr, JNI_ABORT);
+}
+
+static void
+nScriptForEachMultiClippedV(JNIEnv *_env, jobject _this, jlong con,
+                       jlong script, jint slot, jlongArray ains, jlong aout,
+                       jbyteArray params, jint xstart, jint xend,
+                       jint ystart, jint yend, jint zstart, jint zend)
+{
+    LOG_API("nScriptForEachMultiClippedV, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot);
+
+    jint   in_len = _env->GetArrayLength(ains);
+    jlong* in_ptr = _env->GetLongArrayElements(ains, NULL);
+
+    RsAllocation *in_allocs = NULL;
+
+    if (sizeof(RsAllocation) == sizeof(jlong)) {
+      in_allocs = (RsAllocation*)in_ptr;
+
+    } else {
+      // Convert from 64-bit jlong types to the native pointer type.
+
+      in_allocs = new RsAllocation[in_len];
+
+      for (int index = in_len; --index >= 0;) {
+        in_allocs[index] = (RsAllocation)in_ptr[index];
+      }
+    }
+
+    jint   param_len = _env->GetArrayLength(params);
+    jbyte* param_ptr = _env->GetByteArrayElements(params, NULL);
+
+    RsScriptCall sc;
+    sc.xStart = xstart;
+    sc.xEnd = xend;
+    sc.yStart = ystart;
+    sc.yEnd = yend;
+    sc.zStart = zstart;
+    sc.zEnd = zend;
+    sc.strategy = RS_FOR_EACH_STRATEGY_DONT_CARE;
+    sc.arrayStart = 0;
+    sc.arrayEnd = 0;
+    rsScriptForEachMulti((RsContext)con, (RsScript)script, slot, in_allocs, in_len, (RsAllocation)aout, param_ptr, param_len, &sc, sizeof(sc));
+
+    if (sizeof(RsAllocation) != sizeof(jlong)) {
+      delete[] in_allocs;
+    }
+
+    _env->ReleaseLongArrayElements(ains, in_ptr, JNI_ABORT);
+    _env->ReleaseByteArrayElements(params, param_ptr, JNI_ABORT);
+}
+
 // -----------------------------------
 
 static jlong
@@ -1669,6 +1764,8 @@
 {"rsnScriptForEach",                 "(JJIJJ[B)V",                            (void*)nScriptForEachV },
 {"rsnScriptForEachClipped",          "(JJIJJIIIIII)V",                        (void*)nScriptForEachClipped },
 {"rsnScriptForEachClipped",          "(JJIJJ[BIIIIII)V",                      (void*)nScriptForEachClippedV },
+{"rsnScriptForEachMultiClipped",     "(JJI[JJIIIIII)V",                       (void*)nScriptForEachMultiClipped },
+{"rsnScriptForEachMultiClipped",     "(JJI[JJ[BIIIIII)V",                     (void*)nScriptForEachMultiClippedV },
 {"rsnScriptSetVarI",                 "(JJII)V",                               (void*)nScriptSetVarI },
 {"rsnScriptGetVarI",                 "(JJI)I",                                (void*)nScriptGetVarI },
 {"rsnScriptSetVarJ",                 "(JJIJ)V",                               (void*)nScriptSetVarJ },
diff --git a/services/input/Android.mk b/services/input/Android.mk
index 6e944ef..09ecd3a 100644
--- a/services/input/Android.mk
+++ b/services/input/Android.mk
@@ -37,10 +37,12 @@
     libskia \
     libgui \
     libui \
-    libinput
+    libinput \
+    libcrypto \
 
 LOCAL_C_INCLUDES := \
-    external/skia/include/core
+    external/openssl/include \
+    external/skia/include/core \
 
 LOCAL_MODULE:= libinputservice
 
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index e3a3e173..a302cd2 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -48,7 +48,8 @@
 #include <sys/epoll.h>
 #include <sys/ioctl.h>
 #include <sys/limits.h>
-#include <sys/sha1.h>
+
+#include <openssl/sha.h>
 
 /* this macro is used to tell if "bit" is set in "array"
  * it selects a byte from the array, and does a boolean AND
@@ -80,14 +81,14 @@
 }
 
 static String8 sha1(const String8& in) {
-    SHA1_CTX ctx;
-    SHA1Init(&ctx);
-    SHA1Update(&ctx, reinterpret_cast<const u_char*>(in.string()), in.size());
-    u_char digest[SHA1_DIGEST_LENGTH];
-    SHA1Final(digest, &ctx);
+    SHA_CTX ctx;
+    SHA1_Init(&ctx);
+    SHA1_Update(&ctx, reinterpret_cast<const u_char*>(in.string()), in.size());
+    u_char digest[SHA_DIGEST_LENGTH];
+    SHA1_Final(digest, &ctx);
 
     String8 out;
-    for (size_t i = 0; i < SHA1_DIGEST_LENGTH; i++) {
+    for (size_t i = 0; i < SHA_DIGEST_LENGTH; i++) {
         out.appendFormat("%02x", digest[i]);
     }
     return out;
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index b7a1a55..2d1921e 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -3297,6 +3297,11 @@
         return mTethering.getTetherableIfaces();
     }
 
+    public String[] getTetheredDhcpRanges() {
+        enforceConnectivityInternalPermission();
+        return mTethering.getTetheredDhcpRanges();
+    }
+
     public String[] getTetheredIfaces() {
         enforceTetherAccessPermission();
         return mTethering.getTetheredIfaces();
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
old mode 100644
new mode 100755
index baeced7..ae98070
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2839,6 +2839,7 @@
             app.setPid(startResult.pid);
             app.usingWrapper = startResult.usingWrapper;
             app.removed = false;
+            app.killedByAm = false;
             synchronized (mPidsSelfLocked) {
                 this.mPidsSelfLocked.put(startResult.pid, app);
                 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
@@ -12446,6 +12447,7 @@
         app.resetPackageList(mProcessStats);
         app.unlinkDeathRecipient();
         app.makeInactive(mProcessStats);
+        app.waitingToKill = null;
         app.forcingToForeground = null;
         app.foregroundServices = false;
         app.foregroundActivities = false;
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 4d6727c..8f777f9c 100755
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -3370,6 +3370,7 @@
     boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
         boolean didSomething = false;
         TaskRecord lastTask = null;
+        ComponentName homeActivity = null;
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
             int numActivities = activities.size();
@@ -3388,6 +3389,14 @@
                         }
                         return true;
                     }
+                    if (r.isHomeActivity()) {
+                        if (homeActivity != null && homeActivity.equals(r.realActivity)) {
+                            Slog.i(TAG, "Skip force-stop again " + r);
+                            continue;
+                        } else {
+                            homeActivity = r.realActivity;
+                        }
+                    }
                     didSomething = true;
                     Slog.i(TAG, "  Force finishing activity " + r);
                     if (samePackage) {
diff --git a/services/java/com/android/server/am/BaseErrorDialog.java b/services/java/com/android/server/am/BaseErrorDialog.java
old mode 100644
new mode 100755
index 6ede8f8..35bdee0
--- a/services/java/com/android/server/am/BaseErrorDialog.java
+++ b/services/java/com/android/server/am/BaseErrorDialog.java
@@ -27,6 +27,11 @@
 import android.widget.Button;
 
 class BaseErrorDialog extends AlertDialog {
+    private static final int ENABLE_BUTTONS = 0;
+    private static final int DISABLE_BUTTONS = 1;
+
+    private boolean mConsuming = true;
+
     public BaseErrorDialog(Context context) {
         super(context, com.android.internal.R.style.Theme_Dialog_AppError);
 
@@ -41,8 +46,8 @@
 
     public void onStart() {
         super.onStart();
-        setEnabled(false);
-        mHandler.sendMessageDelayed(mHandler.obtainMessage(0), 1000);
+        mHandler.sendEmptyMessage(DISABLE_BUTTONS);
+        mHandler.sendMessageDelayed(mHandler.obtainMessage(ENABLE_BUTTONS), 1000);
     }
 
     public boolean dispatchKeyEvent(KeyEvent event) {
@@ -71,12 +76,12 @@
 
     private Handler mHandler = new Handler() {
         public void handleMessage(Message msg) {
-            if (msg.what == 0) {
+            if (msg.what == ENABLE_BUTTONS) {
                 mConsuming = false;
                 setEnabled(true);
+            } else if (msg.what == DISABLE_BUTTONS) {
+                setEnabled(false);
             }
         }
     };
-
-    private boolean mConsuming = true;
 }
diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java
index 9105103..9c4b7d1 100644
--- a/services/java/com/android/server/am/TaskRecord.java
+++ b/services/java/com/android/server/am/TaskRecord.java
@@ -173,6 +173,11 @@
                 foundFront = true;
             }
         }
+        if (!foundFront && numActivities > 0) {
+            // All activities of this task are finishing. As we ought to have a frontOfTask
+            // activity, make the bottom activity front.
+            mActivities.get(0).frontOfTask = true;
+        }
     }
 
     /**
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index adf1dfc..91b9b07 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -109,6 +109,7 @@
 
     // USB is  192.168.42.1 and 255.255.255.0
     // Wifi is 192.168.43.1 and 255.255.255.0
+    // P2P is 192.168.49.1 and 255.255.255.0
     // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1
     // with 255.255.255.0
 
@@ -117,7 +118,7 @@
         "192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254",
         "192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254",
         "192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254",
-        "192.168.48.2", "192.168.48.254",
+        "192.168.48.2", "192.168.48.254", "192.168.49.2", "192.168.49.254",
     };
 
     private String[] mDefaultDnsServers;
@@ -699,6 +700,10 @@
         return retVal;
     }
 
+    public String[] getTetheredDhcpRanges() {
+        return mDhcpRange;
+    }
+
     public String[] getErroredIfaces() {
         ArrayList<String> list = new ArrayList<String>();
         synchronized (mPublicSync) {
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index 3cdb03c..66615c9 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -24,6 +24,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.List;
 
 public final class Installer {
     private static final String TAG = "Installer";
@@ -342,6 +343,10 @@
         }
     }
 
+    public int pruneDexCache(String cacheSubDir) {
+        return execute("prunedexcache " + cacheSubDir);
+    }
+
     public int freeCache(long freeStorageSize) {
         StringBuilder builder = new StringBuilder("freecache");
         builder.append(' ');
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 7fd9190..0941adb 100755
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -604,10 +604,10 @@
         private final AtomicLong mLastWritten = new AtomicLong(0);
         private final AtomicBoolean mBackgroundWriteRunning = new AtomicBoolean(false);
 
-        private boolean mIsFirstBoot = false;
+        private boolean mIsHistoricalPackageUsageAvailable = true;
 
-        boolean isFirstBoot() {
-            return mIsFirstBoot;
+        boolean isHistoricalPackageUsageAvailable() {
+            return mIsHistoricalPackageUsageAvailable;
         }
 
         void write(boolean force) {
@@ -698,7 +698,7 @@
                         pkg.mLastPackageUsageTimeInMills = timeInMillis;
                     }
                 } catch (FileNotFoundException expected) {
-                    mIsFirstBoot = true;
+                    mIsHistoricalPackageUsageAvailable = false;
                 } catch (IOException e) {
                     Log.w(TAG, "Failed to read package usage times", e);
                 } finally {
@@ -1433,7 +1433,26 @@
             }
 
             if (didDexOptLibraryOrTool) {
-                pruneDexFiles(new File(dataDir, "dalvik-cache"));
+                // If we dexopted a library or tool, then something on the system has
+                // changed. Consider this significant, and wipe away all other
+                // existing dexopt files to ensure we don't leave any dangling around.
+                //
+                // TODO: This should be revisited because it isn't as good an indicator
+                // as it used to be. It used to include the boot classpath but at some point
+                // DexFile.isDexOptNeeded started returning false for the boot
+                // class path files in all cases. It is very possible in a
+                // small maintenance release update that the library and tool
+                // jars may be unchanged but APK could be removed resulting in
+                // unused dalvik-cache files.
+                for (String instructionSet : instructionSets) {
+                    mInstaller.pruneDexCache(instructionSet);
+                }
+
+                // Additionally, delete all dex files from the root directory
+                // since there shouldn't be any there anyway, unless we're upgrading
+                // from an older OS version or a build that contained the "old" style
+                // flat scheme.
+                mInstaller.pruneDexCache(".");
             }
 
             // Collect vendor overlay packages.
@@ -1661,48 +1680,9 @@
         } // synchronized (mInstallLock)
     }
 
-    private static void pruneDexFiles(File cacheDir) {
-        // If we had to do a dexopt of one of the previous
-        // things, then something on the system has changed.
-        // Consider this significant, and wipe away all other
-        // existing dexopt files to ensure we don't leave any
-        // dangling around.
-        //
-        // Additionally, delete all dex files from the root directory
-        // since there shouldn't be any there anyway.
-        //
-        // Note: This isn't as good an indicator as it used to be. It
-        // used to include the boot classpath but at some point
-        // DexFile.isDexOptNeeded started returning false for the boot
-        // class path files in all cases. It is very possible in a
-        // small maintenance release update that the library and tool
-        // jars may be unchanged but APK could be removed resulting in
-        // unused dalvik-cache files.
-        File[] files = cacheDir.listFiles();
-        if (files != null) {
-            for (File file : files) {
-                if (!file.isDirectory()) {
-                    Slog.i(TAG, "Pruning dalvik file: " + file.getAbsolutePath());
-                    file.delete();
-                } else {
-                    File[] subDirList = file.listFiles();
-                    if (subDirList != null) {
-                        for (File subDirFile : subDirList) {
-                            final String fn = subDirFile.getName();
-                            if (fn.startsWith("data@app@") || fn.startsWith("data@app-private@")) {
-                                Slog.i(TAG, "Pruning dalvik file: " + fn);
-                                subDirFile.delete();
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
     @Override
     public boolean isFirstBoot() {
-        return !mRestoredSettings || mPackageUsage.isFirstBoot();
+        return !mRestoredSettings;
     }
 
     @Override
@@ -4149,7 +4129,7 @@
             // The exception is first boot of a non-eng device, which
             // should do a full dexopt.
             boolean eng = "eng".equals(SystemProperties.get("ro.build.type"));
-            if (eng || !isFirstBoot()) {
+            if (eng || (!isFirstBoot() && mPackageUsage.isHistoricalPackageUsageAvailable())) {
                 // TODO: add a property to control this?
                 long dexOptLRUThresholdInMinutes;
                 if (eng) {
@@ -5039,8 +5019,9 @@
          *        only for non-system apps and system app upgrades.
          */
         if (pkg.applicationInfo.nativeLibraryDir != null) {
-            final NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(scanFile);
+            ApkHandle handle = null;
             try {
+                handle = ApkHandle.create(scanFile.getPath());
                 // Enable gross and lame hacks for apps that are built with old
                 // SDK tools. We must scan their APKs for renderscript bitcode and
                 // not launch them if it's present. Don't bother checking on devices
@@ -5155,7 +5136,7 @@
             } catch (IOException ioe) {
                 Slog.e(TAG, "Unable to get canonical file " + ioe.toString());
             } finally {
-                handle.close();
+                IoUtils.closeQuietly(handle);
             }
         }
         pkg.mScanPath = path;
@@ -8788,10 +8769,11 @@
                 nativeLibraryFile.delete();
             }
 
-            final NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(codeFile);
             String[] abiList = (abiOverride != null) ?
                     new String[] { abiOverride } : Build.SUPPORTED_ABIS;
+            ApkHandle handle = null;
             try {
+                handle = ApkHandle.create(codeFile);
                 if (Build.SUPPORTED_64_BIT_ABIS.length > 0 &&
                         abiOverride == null &&
                         NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
@@ -8806,7 +8788,7 @@
                 Slog.e(TAG, "Copying native libraries failed", e);
                 ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
             } finally {
-                handle.close();
+                IoUtils.closeQuietly(handle);
             }
 
             return ret;
@@ -12249,23 +12231,30 @@
                                     final File newNativeDir = new File(newNativePath);
 
                                     if (!isForwardLocked(pkg) && !isExternal(pkg)) {
-                                        // NOTE: We do not report any errors from the APK scan and library
-                                        // copy at this point.
-                                        NativeLibraryHelper.ApkHandle handle =
-                                                new NativeLibraryHelper.ApkHandle(newCodePath);
-                                        final int abi = NativeLibraryHelper.findSupportedAbi(
-                                                handle, Build.SUPPORTED_ABIS);
-                                        if (abi >= 0) {
-                                            NativeLibraryHelper.copyNativeBinariesIfNeededLI(
-                                                    handle, newNativeDir, Build.SUPPORTED_ABIS[abi]);
+                                        ApkHandle handle = null;
+                                        try {
+                                            handle = ApkHandle.create(newCodePath);
+                                            final int abi = NativeLibraryHelper.findSupportedAbi(
+                                                    handle, Build.SUPPORTED_ABIS);
+                                            if (abi >= 0) {
+                                                NativeLibraryHelper.copyNativeBinariesIfNeededLI(
+                                                        handle, newNativeDir, Build.SUPPORTED_ABIS[abi]);
+                                            }
+                                        } catch (IOException ioe) {
+                                            Slog.w(TAG, "Unable to extract native libs for package :"
+                                                    + mp.packageName, ioe);
+                                            returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
+                                        } finally {
+                                            IoUtils.closeQuietly(handle);
                                         }
-                                        handle.close();
                                     }
                                     final int[] users = sUserManager.getUserIds();
-                                    for (int user : users) {
-                                        if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
-                                                newNativePath, user) < 0) {
-                                            returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
+                                    if (returnCode == PackageManager.MOVE_SUCCEEDED) {
+                                        for (int user : users) {
+                                            if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
+                                                    newNativePath, user) < 0) {
+                                                returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
+                                            }
                                         }
                                     }
 
diff --git a/services/java/com/android/server/pm/SELinuxMMAC.java b/services/java/com/android/server/pm/SELinuxMMAC.java
index c78249b..81302b9 100644
--- a/services/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/java/com/android/server/pm/SELinuxMMAC.java
@@ -346,31 +346,21 @@
      */
     public static boolean assignSeinfoValue(PackageParser.Package pkg) {
 
-        /*
-         * Non system installed apps should be treated the same. This
-         * means that any post-loaded apk will be assigned the default
-         * tag, if one exists in the policy, else null, without respect
-         * to the signing key.
-         */
-        if (((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) ||
-            ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)) {
+        // We just want one of the signatures to match.
+        for (Signature s : pkg.mSignatures) {
+            if (s == null)
+                continue;
 
-            // We just want one of the signatures to match.
-            for (Signature s : pkg.mSignatures) {
-                if (s == null)
-                    continue;
+            Policy policy = sSigSeinfo.get(s);
+            if (policy != null) {
+                String seinfo = policy.checkPolicy(pkg.packageName);
+                if (seinfo != null) {
+                    pkg.applicationInfo.seinfo = seinfo;
+                    if (DEBUG_POLICY_INSTALL)
+                        Slog.i(TAG, "package (" + pkg.packageName +
+                               ") labeled with seinfo=" + seinfo);
 
-                Policy policy = sSigSeinfo.get(s);
-                if (policy != null) {
-                    String seinfo = policy.checkPolicy(pkg.packageName);
-                    if (seinfo != null) {
-                        pkg.applicationInfo.seinfo = seinfo;
-                        if (DEBUG_POLICY_INSTALL)
-                            Slog.i(TAG, "package (" + pkg.packageName +
-                                   ") labeled with seinfo=" + seinfo);
-
-                        return true;
-                    }
+                    return true;
                 }
             }
         }
diff --git a/services/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java b/services/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java
index 55dd4ab..24318df 100644
--- a/services/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java
+++ b/services/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java
@@ -42,6 +42,7 @@
     private static final String seappContextsPath = "seapp_contexts";
     private static final String versionPath = "selinux_version";
     private static final String macPermissionsPath = "mac_permissions.xml";
+    private static final String serviceContextsPath = "service_contexts";
 
     public SELinuxPolicyInstallReceiver() {
         super("/data/security/bundle", "sepolicy_bundle", "metadata/", "version");
@@ -65,6 +66,9 @@
 
         new File(contexts, sepolicyPath).renameTo(
                 new File(contexts, sepolicyPath + "_backup"));
+
+        new File(contexts, serviceContextsPath).renameTo(
+                new File(contexts, serviceContextsPath + "_backup"));
     }
 
     private void copyUpdate(File contexts) {
@@ -74,6 +78,7 @@
         new File(updateDir, propertyContextsPath).renameTo(new File(contexts, propertyContextsPath));
         new File(updateDir, fileContextsPath).renameTo(new File(contexts, fileContextsPath));
         new File(updateDir, sepolicyPath).renameTo(new File(contexts, sepolicyPath));
+        new File(updateDir, serviceContextsPath).renameTo(new File(contexts, serviceContextsPath));
     }
 
     private int readInt(BufferedInputStream reader) throws IOException {
@@ -85,13 +90,14 @@
     }
 
     private int[] readChunkLengths(BufferedInputStream bundle) throws IOException {
-        int[] chunks = new int[6];
+        int[] chunks = new int[7];
         chunks[0] = readInt(bundle);
         chunks[1] = readInt(bundle);
         chunks[2] = readInt(bundle);
         chunks[3] = readInt(bundle);
         chunks[4] = readInt(bundle);
         chunks[5] = readInt(bundle);
+        chunks[6] = readInt(bundle);
         return chunks;
     }
 
@@ -112,6 +118,7 @@
             installFile(new File(updateDir, propertyContextsPath), stream, chunkLengths[3]);
             installFile(new File(updateDir, fileContextsPath), stream, chunkLengths[4]);
             installFile(new File(updateDir, sepolicyPath), stream, chunkLengths[5]);
+            installFile(new File(updateDir, serviceContextsPath), stream, chunkLengths[6]);
         } finally {
             IoUtils.closeQuietly(stream);
         }
diff --git a/test-runner/Android.mk b/test-runner/Android.mk
index 0d9e4f1..b12795c 100644
--- a/test-runner/Android.mk
+++ b/test-runner/Android.mk
@@ -20,7 +20,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_JAVA_LIBRARIES := core core-junit framework
+LOCAL_JAVA_LIBRARIES := core-libart core-junit framework
 LOCAL_STATIC_JAVA_LIBRARIES := junit-runner
 
 LOCAL_MODULE:= android.test.runner
diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk
index cb68340..258d9b3 100644
--- a/tools/layoutlib/Android.mk
+++ b/tools/layoutlib/Android.mk
@@ -28,8 +28,8 @@
 built_framework_dep := $(call java-lib-deps,framework-base)
 built_framework_classes := $(call java-lib-files,framework-base)
 
-built_core_dep := $(call java-lib-deps,core)
-built_core_classes := $(call java-lib-files,core)
+built_core_dep := $(call java-lib-deps,core-libart)
+built_core_classes := $(call java-lib-files,core-libart)
 
 built_ext_dep := $(call java-lib-deps,ext)
 built_ext_classes := $(call java-lib-files,ext)
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 8b07208..a38f234 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -109,6 +109,7 @@
 
     INetworkManagementService mNwService;
     private DhcpStateMachine mDhcpStateMachine;
+    private ConnectivityManager mCm;
 
     private P2pStateMachine mP2pStateMachine;
     private AsyncChannel mReplyChannel = new AsyncChannel();
@@ -226,9 +227,6 @@
     /* clients(application) information list. */
     private HashMap<Messenger, ClientInfo> mClientInfoList = new HashMap<Messenger, ClientInfo>();
 
-    /* Is chosen as a unique range to avoid conflict with
-       the range defined in Tethering.java */
-    private static final String[] DHCP_RANGE = {"192.168.49.2", "192.168.49.254"};
     private static final String SERVER_ADDRESS = "192.168.49.1";
 
     /**
@@ -2058,8 +2056,15 @@
         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
+    private void checkAndSetConnectivityInstance() {
+        if (mCm == null) {
+            mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+        }
+    }
+
     private void startDhcpServer(String intf) {
         InterfaceConfiguration ifcg = null;
+        checkAndSetConnectivityInstance();
         try {
             ifcg = mNwService.getInterfaceConfig(intf);
             ifcg.setLinkAddress(new LinkAddress(NetworkUtils.numericToInetAddress(
@@ -2067,17 +2072,30 @@
             ifcg.setInterfaceUp();
             mNwService.setInterfaceConfig(intf, ifcg);
             /* This starts the dnsmasq server */
-            mNwService.startTethering(DHCP_RANGE);
+            String[] tetheringDhcpRanges = mCm.getTetheredDhcpRanges();
+            if (mNwService.isTetheringStarted()) {
+                if (DBG) logd("Stop exist tethering and will restart it");
+                mNwService.stopTethering();
+                mNwService.tetherInterface(intf);
+            }
+            mNwService.startTethering(tetheringDhcpRanges);
         } catch (Exception e) {
             loge("Error configuring interface " + intf + ", :" + e);
             return;
         }
-
         logd("Started Dhcp server on " + intf);
    }
 
     private void stopDhcpServer(String intf) {
         try {
+            for (String temp : mNwService.listTetheredInterfaces()) {
+                logd("List all interfaces " + temp);
+                if (temp.compareTo(intf) != 0 ) {
+                    logd("Found other tethering interface so keep tethering alive");
+                    mNwService.untetherInterface(intf);
+                    return;
+                }
+            }
             mNwService.stopTethering();
         } catch (Exception e) {
             loge("Error stopping Dhcp server" + e);