am 7183a7a5: Merge "Add RIL_UNSOL_RIL_CONNECTED and pass radio technology + 2 to setupDataCall." into honeycomb-LTE

* commit '7183a7a584397142ab7347d6f721011d743fb699':
  Add RIL_UNSOL_RIL_CONNECTED and pass radio technology + 2 to setupDataCall.
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 894e196..93983a6 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -1786,22 +1786,6 @@
         }
     }
 
-    private String getMetaValue(String key) {
-        synchronized (mCacheLock) {
-            final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
-            Cursor c = db.query(TABLE_META,
-                    new String[]{META_VALUE}, META_KEY + "=?", new String[]{key}, null, null, null);
-            try {
-                if (c.moveToNext()) {
-                    return c.getString(0);
-                }
-                return null;
-            } finally {
-                c.close();
-            }
-        }
-    }
-
     public IBinder onBind(Intent intent) {
         return asBinder();
     }
diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
index 9855709..f4693c2 100644
--- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java
+++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
@@ -679,7 +679,6 @@
         @Override
         protected boolean processMessage(Message message) {
             log("IncomingA2dp State->Processing Message: " + message.what);
-            Message deferMsg = new Message();
             switch(message.what) {
                 case CONNECT_HFP_OUTGOING:
                     deferMessage(message);
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index 8204e3c..ccf642c 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -141,7 +141,8 @@
                     Log.wtf("Looper", "Thread identity changed from 0x"
                             + Long.toHexString(ident) + " to 0x"
                             + Long.toHexString(newIdent) + " while dispatching to "
-                            + msg.target + " " + msg.callback + " what=" + msg.what);
+                            + msg.target.getClass().getName() + " "
+                            + msg.callback + " what=" + msg.what);
                 }
                 
                 msg.recycle();
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 0c6ab9e..c8cb1de 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -95,7 +95,7 @@
      * Defines the UID/GID for the NFC service process.
      * @hide
      */
-    public static final int NFC_UID = 1022;
+    public static final int NFC_UID = 1023;
 
     /**
      * Defines the GID for the group that allows write access to the internal media storage.
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 4991914..c1dd911 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -16,6 +16,11 @@
 
 package android.os;
 
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -37,9 +42,6 @@
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
-import android.content.Context;
-import android.util.Log;
-
 import org.apache.harmony.security.asn1.BerInputStream;
 import org.apache.harmony.security.pkcs7.ContentInfo;
 import org.apache.harmony.security.pkcs7.SignedData;
@@ -336,8 +338,21 @@
      * @throws IOException  if writing the recovery command file
      * fails, or if the reboot itself fails.
      */
-    public static void rebootWipeUserData(Context context)
-        throws IOException {
+    public static void rebootWipeUserData(Context context) throws IOException {
+        final ConditionVariable condition = new ConditionVariable();
+
+        Intent intent = new Intent("android.intent.action.MASTER_CLEAR_NOTIFICATION");
+        context.sendOrderedBroadcast(intent, android.Manifest.permission.MASTER_CLEAR,
+                new BroadcastReceiver() {
+                    @Override
+                    public void onReceive(Context context, Intent intent) {
+                        condition.open();
+                    }
+                }, null, 0, null, null);
+
+        // Block until the ordered broadcast has completed.
+        condition.block();
+
         bootCommand(context, "--wipe_data");
     }
 
diff --git a/core/java/android/speech/RecognitionService.java b/core/java/android/speech/RecognitionService.java
index 75a5ed5..32b2d8f 100644
--- a/core/java/android/speech/RecognitionService.java
+++ b/core/java/android/speech/RecognitionService.java
@@ -68,6 +68,8 @@
 
     private static final int MSG_CANCEL = 3;
 
+    private static final int MSG_RESET = 4;
+
     private final Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
@@ -81,6 +83,10 @@
                     break;
                 case MSG_CANCEL:
                     dispatchCancel((IRecognitionListener) msg.obj);
+                    break;
+                case MSG_RESET:
+                    dispatchClearCallback();
+                    break;
             }
         }
     };
@@ -128,6 +134,10 @@
         }
     }
 
+    private void dispatchClearCallback() {
+        mCurrentCallback = null;
+    }
+
     private class StartListeningArgs {
         public final Intent mIntent;
 
@@ -241,7 +251,7 @@
          * @param error code is defined in {@link SpeechRecognizer}
          */
         public void error(int error) throws RemoteException {
-            mCurrentCallback = null;
+            Message.obtain(mHandler, MSG_RESET).sendToTarget();
             mListener.onError(error);
         }
 
@@ -278,7 +288,7 @@
          *        {@link SpeechRecognizer#RESULTS_RECOGNITION} as a parameter
          */
         public void results(Bundle results) throws RemoteException {
-            mCurrentCallback = null;
+            Message.obtain(mHandler, MSG_RESET).sendToTarget();
             mListener.onResults(results);
         }
 
diff --git a/core/java/android/text/util/Rfc822Tokenizer.java b/core/java/android/text/util/Rfc822Tokenizer.java
index 69cf93c..68334e4 100644
--- a/core/java/android/text/util/Rfc822Tokenizer.java
+++ b/core/java/android/text/util/Rfc822Tokenizer.java
@@ -256,7 +256,7 @@
                     if (c == '"') {
                         i++;
                         break;
-                    } else if (c == '\\') {
+                    } else if (c == '\\' && i + 1 < len) {
                         i += 2;
                     } else {
                         i++;
@@ -275,7 +275,7 @@
                     } else if (c == '(') {
                         level++;
                         i++;
-                    } else if (c == '\\') {
+                    } else if (c == '\\' && i + 1 < len) {
                         i += 2;
                     } else {
                         i++;
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
index 3ce0730..e21a02e 100644
--- a/core/java/android/webkit/CacheManager.java
+++ b/core/java/android/webkit/CacheManager.java
@@ -857,6 +857,7 @@
         String cacheControl = headers.getCacheControl();
         if (cacheControl != null) {
             String[] controls = cacheControl.toLowerCase().split("[ ,;]");
+            boolean noCache = false;
             for (int i = 0; i < controls.length; i++) {
                 if (NO_STORE.equals(controls[i])) {
                     return null;
@@ -867,7 +868,12 @@
                 // can only be used in CACHE_MODE_CACHE_ONLY case
                 if (NO_CACHE.equals(controls[i])) {
                     ret.expires = 0;
-                } else if (controls[i].startsWith(MAX_AGE)) {
+                    noCache = true;
+                // if cache control = no-cache has been received, ignore max-age
+                // header, according to http spec:
+                // If a request includes the no-cache directive, it SHOULD NOT
+                // include min-fresh, max-stale, or max-age.
+                } else if (controls[i].startsWith(MAX_AGE) && !noCache) {
                     int separator = controls[i].indexOf('=');
                     if (separator < 0) {
                         separator = controls[i].indexOf(':');
diff --git a/core/jni/android_bluetooth_BluetoothSocket.cpp b/core/jni/android_bluetooth_BluetoothSocket.cpp
index b87f7c4..d09c4e9 100644
--- a/core/jni/android_bluetooth_BluetoothSocket.cpp
+++ b/core/jni/android_bluetooth_BluetoothSocket.cpp
@@ -448,7 +448,7 @@
 #ifdef HAVE_BLUETOOTH
     LOGV("%s", __FUNCTION__);
 
-    int ret;
+    int ret, total;
     jbyte *b;
     int sz;
     struct asocket *s = get_socketData(env, obj);
@@ -471,15 +471,21 @@
         return -1;
     }
 
-    ret = asocket_write(s, &b[offset], length, -1);
-    if (ret < 0) {
-        jniThrowIOException(env, errno);
-        env->ReleaseByteArrayElements(jb, b, JNI_ABORT);
-        return -1;
+    total = 0;
+    while (length > 0) {
+        ret = asocket_write(s, &b[offset], length, -1);
+        if (ret < 0) {
+            jniThrowIOException(env, errno);
+            env->ReleaseByteArrayElements(jb, b, JNI_ABORT);
+            return -1;
+        }
+        offset += ret;
+        total += ret;
+        length -= ret;
     }
 
     env->ReleaseByteArrayElements(jb, b, JNI_ABORT);  // no need to commit
-    return (jint)ret;
+    return (jint)total;
 
 #endif
     jniThrowIOException(env, ENOSYS);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0c9a2ef..2a4d1b2 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -57,6 +57,7 @@
     <protected-broadcast android:name="android.intent.action.NEW_OUTGOING_CALL" />
     <protected-broadcast android:name="android.intent.action.REBOOT" />
     <protected-broadcast android:name="android.intent.action.DOCK_EVENT" />
+    <protected-broadcast android:name="android.intent.action.MASTER_CLEAR_NOTIFICATION" />
 
     <protected-broadcast android:name="android.app.action.ENTER_CAR_MODE" />
     <protected-broadcast android:name="android.app.action.EXIT_CAR_MODE" />
@@ -1031,7 +1032,7 @@
     <permission android:name="android.permission.STOP_APP_SWITCHES"
         android:label="@string/permlab_stopAppSwitches"
         android:description="@string/permdesc_stopAppSwitches"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signatureOrSystem" />
 
     <!-- Allows an application to retrieve the current state of keys and
          switches.  This is only for use by the system.-->
diff --git a/core/tests/coretests/src/android/content/pm/PackageHelperTests.java b/core/tests/coretests/src/android/content/pm/PackageHelperTests.java
new file mode 100644
index 0000000..27112a6
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/PackageHelperTests.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2011 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.content.pm;
+
+import com.android.internal.content.PackageHelper;
+
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.storage.IMountService;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+public class PackageHelperTests extends AndroidTestCase {
+    private static final boolean localLOGV = true;
+    public static final String TAG = "PackageHelperTests";
+    protected final String PREFIX = "android.content.pm";
+    private IMountService mMs;
+    private String fullId;
+    private String fullId2;
+
+    private IMountService getMs() {
+        IBinder service = ServiceManager.getService("mount");
+        if (service != null) {
+            return IMountService.Stub.asInterface(service);
+        } else {
+            Log.e(TAG, "Can't get mount service");
+        }
+        return null;
+    }
+
+    private void cleanupContainers() throws RemoteException {
+        Log.d(TAG,"cleanUp");
+        IMountService ms = getMs();
+        String[] containers = ms.getSecureContainerList();
+        for (int i = 0; i < containers.length; i++) {
+            if (containers[i].startsWith(PREFIX)) {
+                Log.d(TAG,"cleaing up "+containers[i]);
+                ms.destroySecureContainer(containers[i], true);
+            }
+        }
+    }
+
+    void failStr(String errMsg) {
+        Log.w(TAG, "errMsg=" + errMsg);
+        fail(errMsg);
+    }
+
+    void failStr(Exception e) {
+        failStr(e.getMessage());
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        if (localLOGV) Log.i(TAG, "Cleaning out old test containers");
+        cleanupContainers();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        if (localLOGV) Log.i(TAG, "Cleaning out old test containers");
+        cleanupContainers();
+    }
+
+    public void testMountAndPullSdCard() {
+        try {
+            fullId = PREFIX;
+            fullId2 = PackageHelper.createSdDir(1024, fullId, "none", android.os.Process.myUid());
+
+            Log.d(TAG,PackageHelper.getSdDir(fullId));
+            PackageHelper.unMountSdDir(fullId);
+
+            Runnable r1 = getMountRunnable();
+            Runnable r2 = getDestroyRunnable();
+            Thread thread = new Thread(r1);
+            Thread thread2 = new Thread(r2);
+            thread2.start();
+            thread.start();
+        } catch (Exception e) {
+            failStr(e);
+        }
+    }
+
+    public Runnable getMountRunnable() {
+        Runnable r = new Runnable () {
+            public void run () {
+                try {
+                    Thread.sleep(5);
+                    String path = PackageHelper.mountSdDir(fullId, "none",
+                            android.os.Process.myUid());
+                    Log.e(TAG, "mount done " + path);
+                } catch (IllegalArgumentException iae) {
+                    throw iae;
+                } catch (Throwable t) {
+                    Log.e(TAG, "mount failed", t);
+                }
+            }
+        };
+        return r;
+    }
+
+    public Runnable getDestroyRunnable() {
+        Runnable r = new Runnable () {
+            public void run () {
+                try {
+                    PackageHelper.destroySdDir(fullId);
+                    Log.e(TAG, "destroy done: " + fullId);
+                } catch (Throwable t) {
+                    Log.e(TAG, "destroy failed", t);
+                }
+            }
+        };
+        return r;
+    }
+}
diff --git a/core/tests/coretests/src/android/text/TextUtilsTest.java b/core/tests/coretests/src/android/text/TextUtilsTest.java
index e111662..79d57f1 100644
--- a/core/tests/coretests/src/android/text/TextUtilsTest.java
+++ b/core/tests/coretests/src/android/text/TextUtilsTest.java
@@ -255,6 +255,23 @@
         assertEquals("Foo Bar", tokens[0].getAddress());
     }
 
+    @SmallTest
+    public void testRfc822FindToken() {
+        Rfc822Tokenizer tokenizer = new Rfc822Tokenizer();
+        //                0           1         2           3         4
+        //                0 1234 56789012345678901234 5678 90123456789012345
+        String address = "\"Foo\" <foo@google.com>, \"Bar\" <bar@google.com>";
+        assertEquals(0, tokenizer.findTokenStart(address, 21));
+        assertEquals(22, tokenizer.findTokenEnd(address, 21));
+        assertEquals(24, tokenizer.findTokenStart(address, 25));
+        assertEquals(46, tokenizer.findTokenEnd(address, 25));
+    }
+
+    @SmallTest
+    public void testRfc822FindTokenWithError() {
+        assertEquals(9, new Rfc822Tokenizer().findTokenEnd("\"Foo Bar\\", 0));
+    }
+
     @LargeTest
     public void testEllipsize() {
         CharSequence s1 = "The quick brown fox jumps over \u00FEhe lazy dog.";
diff --git a/graphics/java/android/graphics/YuvImage.java b/graphics/java/android/graphics/YuvImage.java
index 9368da6..af3f276 100644
--- a/graphics/java/android/graphics/YuvImage.java
+++ b/graphics/java/android/graphics/YuvImage.java
@@ -36,7 +36,7 @@
     private final static int WORKING_COMPRESS_STORAGE = 4096;
 
    /**
-     * The YUV format as defined in {@link PixelFormat}.
+     * The YUV format as defined in {@link ImageFormat}.
      */
     private int mFormat;
 
@@ -67,7 +67,7 @@
      *
      * @param yuv     The YUV data. In the case of more than one image plane, all the planes must be
      *                concatenated into a single byte array.
-     * @param format  The YUV data format as defined in {@link PixelFormat}.
+     * @param format  The YUV data format as defined in {@link ImageFormat}.
      * @param width   The width of the YuvImage.
      * @param height  The height of the YuvImage.
      * @param strides (Optional) Row bytes of each image plane. If yuv contains padding, the stride
@@ -152,7 +152,7 @@
     }
 
     /**
-     * @return the YUV format as defined in {@link PixelFormat}.
+     * @return the YUV format as defined in {@link ImageFormat}.
      */
     public int getYuvFormat() {
         return mFormat;
diff --git a/media/java/android/media/ThumbnailUtils.java b/media/java/android/media/ThumbnailUtils.java
index 7fdf448..7c181ee 100644
--- a/media/java/android/media/ThumbnailUtils.java
+++ b/media/java/android/media/ThumbnailUtils.java
@@ -83,7 +83,7 @@
      *
      * @param filePath the path of image file
      * @param kind could be MINI_KIND or MICRO_KIND
-     * @return Bitmap
+     * @return Bitmap, or null on failures
      *
      * @hide This method is only used by media framework and media provider internally.
      */
@@ -123,6 +123,8 @@
                 bitmap = BitmapFactory.decodeFileDescriptor(fd, null, options);
             } catch (IOException ex) {
                 Log.e(TAG, "", ex);
+            } catch (OutOfMemoryError oom) {
+                Log.e(TAG, "Unable to decode file " + filePath + ". OutOfMemoryError.", oom);
             }
         }
 
diff --git a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
index cf38bd1..ed1af49 100644
--- a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
+++ b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
@@ -57,7 +57,6 @@
 
     // protected by NfcAdapterExtras.class, and final after first construction
     private static INfcAdapterExtras sService;
-    private static boolean sIsInitialized = false;
     private static NfcAdapterExtras sSingleton;
     private static NfcExecutionEnvironment sEmbeddedEe;
     private static CardEmulationRoute sRouteOff;
@@ -74,14 +73,22 @@
      */
     public static NfcAdapterExtras get(NfcAdapter adapter) {
         synchronized(NfcAdapterExtras.class) {
-            if (!sIsInitialized) {
-               sIsInitialized = true;
-               sService = adapter.getNfcAdapterExtrasInterface();
-               sEmbeddedEe = new NfcExecutionEnvironment(sService);
-               sRouteOff = new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null);
-               sRouteOnWhenScreenOn = new CardEmulationRoute(
-                       CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, sEmbeddedEe);
-               sSingleton = new NfcAdapterExtras();
+            if (sSingleton == null) {
+                try {
+                    sService = adapter.getNfcAdapterExtrasInterface();
+                    sEmbeddedEe = new NfcExecutionEnvironment(sService);
+                    sRouteOff = new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null);
+                    sRouteOnWhenScreenOn = new CardEmulationRoute(
+                            CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, sEmbeddedEe);
+                    sSingleton = new NfcAdapterExtras();
+                } finally {
+                    if (sSingleton == null) {
+                        sService = null;
+                        sEmbeddedEe = null;
+                        sRouteOff = null;
+                        sRouteOnWhenScreenOn = null;
+                    }
+                }
             }
             return sSingleton;
         }
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_0.png
index adde938..c8ddfce 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_0.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim1.png
index adde938..6b6a6df 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim1.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_0.png
index c61cce7..827d84a 100755
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_0.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim1.png
index c61cce7..edc6023 100755
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim1.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim1.png
Binary files differ
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index f4dc69a..372d9b5 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -526,18 +526,8 @@
      */
     public NetworkInfo getActiveNetworkInfo() {
         enforceAccessPermission();
-        for (int type=0; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
-            if (mNetConfigs[type] == null || !mNetConfigs[type].isDefault()) {
-                continue;
-            }
-            NetworkStateTracker t = mNetTrackers[type];
-            NetworkInfo info = t.getNetworkInfo();
-            if (info.isConnected()) {
-                if (DBG && type != mActiveDefaultNetwork) {
-                    loge("connected default network is not mActiveDefaultNetwork!");
-                }
-                return info;
-            }
+        if (mActiveDefaultNetwork != -1) {
+            return mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
         }
         return null;
     }
@@ -1305,6 +1295,7 @@
                     }
                     if (!teardown(otherNet)) {
                         loge("Network declined teardown request");
+                        teardown(thisNet);
                         return;
                     }
                 }
@@ -1354,6 +1345,19 @@
                 handleApplyDefaultProxy(netType);
                 addDefaultRoute(mNetTrackers[netType]);
             } else {
+                // many radios add a default route even when we don't want one.
+                // remove the default interface unless we need it for our active network
+                if (mActiveDefaultNetwork != -1) {
+                    LinkProperties linkProperties =
+                            mNetTrackers[mActiveDefaultNetwork].getLinkProperties();
+                    LinkProperties newLinkProperties =
+                            mNetTrackers[netType].getLinkProperties();
+                    String defaultIface = linkProperties.getInterfaceName();
+                    if (defaultIface != null &&
+                            !defaultIface.equals(newLinkProperties.getInterfaceName())) {
+                        removeDefaultRoute(mNetTrackers[netType]);
+                    }
+                }
                 addPrivateDnsRoutes(mNetTrackers[netType]);
             }
         } else {
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 91ada6b..a34b7dc 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -1532,7 +1532,8 @@
         } catch (NativeDaemonConnectorException e) {
             int code = e.getCode();
             if (code == VoldResponseCode.OpFailedStorageNotFound) {
-                throw new IllegalArgumentException(String.format("Container '%s' not found", id));
+                Slog.i(TAG, String.format("Container '%s' not found", id));
+                return null;
             } else {
                 throw new IllegalStateException(String.format("Unexpected response code %d", code));
             }
diff --git a/services/java/com/android/server/VibratorService.java b/services/java/com/android/server/VibratorService.java
index 2fcdb5d..c39dc80 100755
--- a/services/java/com/android/server/VibratorService.java
+++ b/services/java/com/android/server/VibratorService.java
@@ -247,6 +247,7 @@
     // Lock held on mVibrations
     private void startNextVibrationLocked() {
         if (mVibrations.size() <= 0) {
+            mCurrentVibration = null;
             return;
         }
         mCurrentVibration = mVibrations.getFirst();
@@ -273,17 +274,27 @@
             Vibration vib = iter.next();
             if (vib.mToken == token) {
                 iter.remove();
+                unlinkVibration(vib);
                 return vib;
             }
         }
         // We might be looking for a simple vibration which is only stored in
         // mCurrentVibration.
         if (mCurrentVibration != null && mCurrentVibration.mToken == token) {
+            unlinkVibration(mCurrentVibration);
             return mCurrentVibration;
         }
         return null;
     }
 
+    private void unlinkVibration(Vibration vib) {
+        if (vib.mPattern != null) {
+            // If Vibration object has a pattern,
+            // the Vibration object has also been linkedToDeath.
+            vib.mToken.unlinkToDeath(vib, 0);
+        }
+    }
+
     private class VibrateThread extends Thread {
         final Vibration mVibration;
         boolean mDone;
@@ -360,6 +371,7 @@
                     // If this vibration finished naturally, start the next
                     // vibration.
                     mVibrations.remove(mVibration);
+                    unlinkVibration(mVibration);
                     startNextVibrationLocked();
                 }
             }
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 267c76a..50fffd0 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -6996,8 +6996,9 @@
 
         addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
 
-        if (Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.WTF_IS_FATAL, 0) != 0) {
+        if (r != null && r.pid != Process.myPid() &&
+                Settings.Secure.getInt(mContext.getContentResolver(),
+                        Settings.Secure.WTF_IS_FATAL, 0) != 0) {
             crashApplication(r, crashInfo);
             return true;
         } else {
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 3561862..63ce0bd 100755
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -203,7 +203,7 @@
     // flags to trigger NTP or XTRA data download when network becomes available
     // initialized to true so we do NTP and XTRA when the network comes up after booting
     private boolean mInjectNtpTimePending = true;
-    private boolean mDownloadXtraDataPending = false;
+    private boolean mDownloadXtraDataPending = true;
 
     // true if GPS is navigating
     private boolean mNavigating;
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
old mode 100755
new mode 100644
index 7373cbb..5471289
--- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
@@ -40,6 +40,7 @@
 
 import java.text.ParseException;
 import java.util.List;
+import java.util.regex.Pattern;
 
 /**
  * {@hide}
@@ -386,8 +387,8 @@
         Connection dial(String originalNumber) throws SipException {
             String calleeSipUri = originalNumber;
             if (!calleeSipUri.contains("@")) {
-                calleeSipUri = mProfile.getUriString().replaceFirst(
-                        mProfile.getUserName() + "@",
+                String replaceStr = Pattern.quote(mProfile.getUserName() + "@");
+                calleeSipUri = mProfile.getUriString().replaceFirst(replaceStr,
                         calleeSipUri + "@");
             }
             try {
diff --git a/tests/CoreTests/android/core/HttpHeaderTest.java b/tests/CoreTests/android/core/HttpHeaderTest.java
index a5d48578..eedbc3f 100644
--- a/tests/CoreTests/android/core/HttpHeaderTest.java
+++ b/tests/CoreTests/android/core/HttpHeaderTest.java
@@ -19,12 +19,19 @@
 import org.apache.http.util.CharArrayBuffer;
 
 import android.net.http.Headers;
+import android.util.Log;
+import android.webkit.CacheManager;
+import android.webkit.CacheManager.CacheResult;
+
+import java.lang.reflect.Method;
 
 public class HttpHeaderTest extends AndroidTestCase {
 
     static final String LAST_MODIFIED = "Last-Modified: Fri, 18 Jun 2010 09:56:47 GMT";
     static final String CACHE_CONTROL_MAX_AGE = "Cache-Control:max-age=15";
     static final String CACHE_CONTROL_PRIVATE = "Cache-Control: private";
+    static final String CACHE_CONTROL_COMPOUND = "Cache-Control: no-cache, max-age=200000";
+    static final String CACHE_CONTROL_COMPOUND2 = "Cache-Control: max-age=200000, no-cache";
 
     /**
      * Tests that cache control header supports multiple instances of the header,
@@ -59,4 +66,39 @@
         h.parseHeader(buffer);
         assertEquals("max-age=15,private", h.getCacheControl());
     }
+
+    // Test that cache behaves correctly when receiving a compund
+    // cache-control statement containing no-cache and max-age argument.
+    //
+    // If a cache control header contains both a max-age arument and
+    // a no-cache argument the max-age argument should be ignored.
+    // The resource can be cached, but a validity check must be done on
+    // every request. Test case checks that the expiry time is 0 for
+    // this item, so item will be validated on subsequent requests.
+    public void testCacheControlMultipleArguments() throws Exception {
+        // get private method CacheManager.parseHeaders()
+        Method m = CacheManager.class.getDeclaredMethod("parseHeaders",
+                new Class[] {int.class, Headers.class, String.class});
+        m.setAccessible(true);
+
+        // create indata
+        Headers h = new Headers();
+        CharArrayBuffer buffer = new CharArrayBuffer(64);
+        buffer.append(CACHE_CONTROL_COMPOUND);
+        h.parseHeader(buffer);
+
+        CacheResult c = (CacheResult)m.invoke(null, 200, h, "text/html");
+
+        // Check that expires is set to 0, to ensure that no-cache has overridden
+        // the max-age argument
+        assertEquals(0, c.getExpires());
+
+        // check reverse order
+        buffer.clear();
+        buffer.append(CACHE_CONTROL_COMPOUND2);
+        h.parseHeader(buffer);
+
+        c = (CacheResult)m.invoke(null, 200, h, "text/html");
+        assertEquals(0, c.getExpires());
+    }
 }
diff --git a/voip/java/com/android/server/sip/SipHelper.java b/voip/java/com/android/server/sip/SipHelper.java
index ac580e7..4ee86b6 100644
--- a/voip/java/com/android/server/sip/SipHelper.java
+++ b/voip/java/com/android/server/sip/SipHelper.java
@@ -27,6 +27,8 @@
 import java.util.ArrayList;
 import java.util.EventObject;
 import java.util.List;
+import java.util.regex.Pattern;
+
 import javax.sip.ClientTransaction;
 import javax.sip.Dialog;
 import javax.sip.DialogTerminatedEvent;
@@ -215,9 +217,11 @@
             String tag) throws ParseException, SipException {
         FromHeader fromHeader = createFromHeader(userProfile, tag);
         ToHeader toHeader = createToHeader(userProfile);
+
+        String replaceStr = Pattern.quote(userProfile.getUserName() + "@");
         SipURI requestURI = mAddressFactory.createSipURI(
-                userProfile.getUriString().replaceFirst(
-                userProfile.getUserName() + "@", ""));
+                userProfile.getUriString().replaceFirst(replaceStr, ""));
+
         List<ViaHeader> viaHeaders = createViaHeaders();
         CallIdHeader callIdHeader = createCallIdHeader();
         CSeqHeader cSeqHeader = createCSeqHeader(requestType);
diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp
index c031eee..41fedce 100644
--- a/voip/jni/rtp/AudioGroup.cpp
+++ b/voip/jni/rtp/AudioGroup.cpp
@@ -30,6 +30,7 @@
 
 #define LOG_TAG "AudioGroup"
 #include <cutils/atomic.h>
+#include <cutils/properties.h>
 #include <utils/Log.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
@@ -619,6 +620,14 @@
     if (mode < 0 || mode > LAST_MODE) {
         return false;
     }
+    //FIXME: temporary code to overcome echo and mic gain issues on herring board.
+    // Must be modified/removed when proper support for voice processing query and control
+    // is included in audio framework
+    char value[PROPERTY_VALUE_MAX];
+    property_get("ro.product.board", value, "");
+    if (mode == NORMAL && !strcmp(value, "herring")) {
+        mode = ECHO_SUPPRESSION;
+    }
     if (mode == ECHO_SUPPRESSION && AudioSystem::getParameters(
         0, String8("ec_supported")) == "ec_supported=yes") {
         mode = NORMAL;