Merge "Pause drawing when not visible" into ics-mr1
diff --git a/api/current.txt b/api/current.txt
index d83659f..f07e66b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -15132,6 +15132,7 @@
 
   public class RemoteException extends android.util.AndroidException {
     ctor public RemoteException();
+    ctor public RemoteException(java.lang.String);
   }
 
   public class ResultReceiver implements android.os.Parcelable {
@@ -15226,6 +15227,10 @@
     method public abstract void released();
   }
 
+  public class TransactionTooLargeException extends android.os.RemoteException {
+    ctor public TransactionTooLargeException();
+  }
+
   public class Vibrator {
     method public void cancel();
     method public boolean hasVibrator();
@@ -24825,6 +24830,7 @@
   }
 
   public class SpellCheckerSession {
+    method public void cancel();
     method public void close();
     method public android.view.textservice.SpellCheckerInfo getSpellChecker();
     method public void getSuggestions(android.view.textservice.TextInfo, int);
diff --git a/core/java/android/os/RemoteException.java b/core/java/android/os/RemoteException.java
index 9d76156..e30d24f 100644
--- a/core/java/android/os/RemoteException.java
+++ b/core/java/android/os/RemoteException.java
@@ -24,4 +24,8 @@
     public RemoteException() {
         super();
     }
+
+    public RemoteException(String message) {
+        super(message);
+    }
 }
diff --git a/core/java/android/os/TransactionTooLargeException.java b/core/java/android/os/TransactionTooLargeException.java
new file mode 100644
index 0000000..25f09e8
--- /dev/null
+++ b/core/java/android/os/TransactionTooLargeException.java
@@ -0,0 +1,59 @@
+/*
+ * 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.os;
+import android.os.RemoteException;
+
+/**
+ * The Binder transaction failed because it was too large.
+ * <p>
+ * During a remote procedure call, the arguments and the return value of the call
+ * are transferred as {@link Parcel} objects stored in the Binder transaction buffer.
+ * If the arguments or the return value are too large to fit in the transaction buffer,
+ * then the call will fail and {@link TransactionTooLargeException} will be thrown.
+ * </p><p>
+ * The Binder transaction buffer has a limited fixed size, currently 1Mb, which
+ * is shared by all transactions in progress for the process.  Consequently this
+ * exception can be thrown when there are many transactions in progress even when
+ * most of the individual transactions are of moderate size.
+ * </p><p>
+ * There are two possible outcomes when a remote procedure call throws
+ * {@link TransactionTooLargeException}.  Either the client was unable to send
+ * its request to the service (most likely if the arguments were too large to fit in
+ * the transaction buffer), or the service was unable to send its response back
+ * to the client (most likely if the return value was too large to fit
+ * in the transaction buffer).  It is not possible to tell which of these outcomes
+ * actually occurred.  The client should assume that a partial failure occurred.
+ * </p><p>
+ * The key to avoiding {@link TransactionTooLargeException} is to keep all
+ * transactions relatively small.  Try to minimize the amount of memory needed to create
+ * a {@link Parcel} for the arguments and the return value of the remote procedure call.
+ * Avoid transferring huge arrays of strings or large bitmaps.
+ * If possible, try to break up big requests into smaller pieces.
+ * </p><p>
+ * If you are implementing a service, it may help to impose size or complexity
+ * contraints on the queries that clients can perform.  For example, if the result set
+ * could become large, then don't allow the client to request more than a few records
+ * at a time.  Alternately, instead of returning all of the available data all at once,
+ * return the essential information first and make the client ask for additional information
+ * later as needed.
+ * </p>
+ */
+public class TransactionTooLargeException extends RemoteException {
+    public TransactionTooLargeException() {
+        super();
+    }
+}
diff --git a/core/java/android/view/textservice/SpellCheckerSession.java b/core/java/android/view/textservice/SpellCheckerSession.java
index 01b114c..0eb6e27 100644
--- a/core/java/android/view/textservice/SpellCheckerSession.java
+++ b/core/java/android/view/textservice/SpellCheckerSession.java
@@ -146,6 +146,13 @@
     }
 
     /**
+     * Cancel pending and running spell check tasks
+     */
+    public void cancel() {
+        mSpellCheckerSessionListenerImpl.cancel();
+    }
+
+    /**
      * Finish this session and allow TextServicesManagerService to disconnect the bound spell
      * checker.
      */
@@ -242,6 +249,13 @@
             }
         }
 
+        public void cancel() {
+            if (DBG) {
+                Log.w(TAG, "cancel");
+            }
+            processOrEnqueueTask(new SpellCheckerParams(TASK_CANCEL, null, 0, false));
+        }
+
         public void getSuggestionsMultiple(
                 TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) {
             if (DBG) {
@@ -275,8 +289,22 @@
             if (DBG) {
                 Log.d(TAG, "process or enqueue task: " + mISpellCheckerSession);
             }
+            SpellCheckerParams closeTask = null;
             if (mISpellCheckerSession == null) {
+                if (scp.mWhat == TASK_CANCEL) {
+                    while (!mPendingTasks.isEmpty()) {
+                        final SpellCheckerParams tmp = mPendingTasks.poll();
+                        if (tmp.mWhat == TASK_CLOSE) {
+                            // Only one close task should be processed, while we need to remove all
+                            // close tasks from the queue
+                            closeTask = tmp;
+                        }
+                    }
+                }
                 mPendingTasks.offer(scp);
+                if (closeTask != null) {
+                    mPendingTasks.offer(closeTask);
+                }
             } else {
                 processTask(scp);
             }
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 388920c..c194559 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -1404,4 +1404,17 @@
     native void nativeSslClientCert(int handle,
                                     byte[] pkcs8EncodedPrivateKey,
                                     byte[][] asn1DerEncodedCertificateChain);
+
+    /**
+     * Returns true when the contents of the frame is an RTL or vertical-rl
+     * page. This is used for determining whether a frame should be initially
+     * scrolled right-most as opposed to left-most.
+     * @return true when the frame should be initially scrolled right-most
+     * based on the text direction and writing mode.
+     */
+    /* package */ boolean getShouldStartScrolledRight() {
+        return nativeGetShouldStartScrolledRight(mNativeFrame);
+    }
+
+    private native boolean nativeGetShouldStartScrolledRight(int nativeBrowserFrame);
 }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index c8f0270..03d6511 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -8760,27 +8760,6 @@
                     isPictureAfterFirstLayout, registerPageSwapCallback);
         }
         final Point viewSize = draw.mViewSize;
-        if (isPictureAfterFirstLayout) {
-            // Reset the last sent data here since dealing with new page.
-            mLastWidthSent = 0;
-            mZoomManager.onFirstLayout(draw);
-            if (!mDrawHistory) {
-                // Do not send the scroll event for this particular
-                // scroll message.  Note that a scroll event may
-                // still be fired if the user scrolls before the
-                // message can be handled.
-                mSendScrollEvent = false;
-                setContentScrollTo(viewState.mScrollX, viewState.mScrollY);
-                mSendScrollEvent = true;
-
-                // As we are on a new page, remove the WebTextView. This
-                // is necessary for page loads driven by webkit, and in
-                // particular when the user was on a password field, so
-                // the WebTextView was visible.
-                clearTextEntry();
-            }
-        }
-
         // We update the layout (i.e. request a layout from the
         // view system) if the last view size that we sent to
         // WebCore matches the view size of the picture we just
@@ -8793,7 +8772,25 @@
         mSendScrollEvent = false;
         recordNewContentSize(draw.mContentSize.x,
                 draw.mContentSize.y, updateLayout);
+
+        if (isPictureAfterFirstLayout) {
+            // Reset the last sent data here since dealing with new page.
+            mLastWidthSent = 0;
+            mZoomManager.onFirstLayout(draw);
+            int scrollX = viewState.mShouldStartScrolledRight
+                    ? getContentWidth() : viewState.mScrollX;
+            int scrollY = viewState.mScrollY;
+            setContentScrollTo(scrollX, scrollY);
+            if (!mDrawHistory) {
+                // As we are on a new page, remove the WebTextView. This
+                // is necessary for page loads driven by webkit, and in
+                // particular when the user was on a password field, so
+                // the WebTextView was visible.
+                clearTextEntry();
+            }
+        }
         mSendScrollEvent = true;
+
         if (DebugFlags.WEB_VIEW) {
             Rect b = draw.mInvalRegion.getBounds();
             Log.v(LOGTAG, "NEW_PICTURE_MSG_ID {" +
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 754d6e9..cd61481 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1982,6 +1982,7 @@
         int mScrollY;
         boolean mMobileSite;
         boolean mIsRestored;
+        boolean mShouldStartScrolledRight;
     }
 
     static class DrawData {
@@ -2382,6 +2383,7 @@
             viewState.mMobileSite = false;
             // for non-mobile site, we don't need minPrefWidth, set it as 0
             viewState.mScrollX = 0;
+            viewState.mShouldStartScrolledRight = false;
             Message.obtain(mWebView.mPrivateHandler,
                     WebView.UPDATE_ZOOM_RANGE, viewState).sendToTarget();
             return;
@@ -2412,6 +2414,11 @@
         mInitialViewState.mDefaultScale = adjust;
         mInitialViewState.mScrollX = mRestoredX;
         mInitialViewState.mScrollY = mRestoredY;
+        mInitialViewState.mShouldStartScrolledRight = (mRestoredX == 0)
+                && (mRestoredY == 0)
+                && (mBrowserFrame != null)
+                && mBrowserFrame.getShouldStartScrolledRight();
+
         mInitialViewState.mMobileSite = (0 == mViewportWidth);
         if (mIsRestored) {
             mInitialViewState.mIsRestored = true;
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index 87c3e9b..ebb2604 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -76,7 +76,7 @@
         mIds = new int[size];
         mSpellCheckSpans = new SpellCheckSpan[size];
 
-        setLocale(mTextView.getLocale());
+        setLocale(mTextView.getTextServicesLocale());
 
         mCookie = hashCode();
     }
@@ -173,7 +173,7 @@
     }
 
     public void spellCheck(int start, int end) {
-        final Locale locale = mTextView.getLocale();
+        final Locale locale = mTextView.getTextServicesLocale();
         if (mCurrentLocale == null || (!(mCurrentLocale.equals(locale)))) {
             setLocale(locale);
             // Re-check the entire text
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5833afd..bc8721a 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -36,7 +36,6 @@
 import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
 import android.inputmethodservice.ExtractEditText;
-import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
@@ -101,7 +100,6 @@
 import android.util.TypedValue;
 import android.view.ActionMode;
 import android.view.ActionMode.Callback;
-import android.view.ContextMenu;
 import android.view.DragEvent;
 import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
@@ -133,6 +131,8 @@
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
+import android.view.textservice.SpellCheckerSubtype;
+import android.view.textservice.TextServicesManager;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.RemoteViews.RemoteView;
 
@@ -8355,10 +8355,12 @@
                         // When the cursor moves, the word that was typed may need spell check
                         mSpellChecker.onSelectionChanged();
                     }
-                    if (isCursorInsideEasyCorrectionSpan()) {
-                        showSuggestions();
-                    } else if (hasInsertionController()) {
-                        getInsertionController().show();
+                    if (!extractedTextModeWillBeStarted()) {
+                        if (isCursorInsideEasyCorrectionSpan()) {
+                            showSuggestions();
+                        } else if (hasInsertionController()) {
+                            getInsertionController().show();
+                        }
                     }
                 }
 
@@ -8904,21 +8906,18 @@
     /**
      * This is a temporary method. Future versions may support multi-locale text.
      *
-     * @return The current locale used in this TextView, based on the current IME's locale,
-     * or the system default locale if this is not defined.
+     * @return The locale that should be used for a word iterator and a spell checker
+     * in this TextView, based on the current spell checker settings,
+     * the current IME's locale, or the system default locale.
      * @hide
      */
-    public Locale getLocale() {
+    public Locale getTextServicesLocale() {
         Locale locale = Locale.getDefault();
-        final InputMethodManager imm = InputMethodManager.peekInstance();
-        if (imm != null) {
-            final InputMethodSubtype currentInputMethodSubtype = imm.getCurrentInputMethodSubtype();
-            if (currentInputMethodSubtype != null) {
-                String localeString = currentInputMethodSubtype.getLocale();
-                if (!TextUtils.isEmpty(localeString)) {
-                    locale = new Locale(localeString);
-                }
-            }
+        final TextServicesManager textServicesManager = (TextServicesManager)
+                mContext.getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE);
+        final SpellCheckerSubtype subtype = textServicesManager.getCurrentSpellCheckerSubtype(true);
+        if (subtype != null) {
+            locale = new Locale(subtype.getLocale());
         }
         return locale;
     }
@@ -8933,7 +8932,7 @@
      */
     public WordIterator getWordIterator() {
         if (mWordIterator == null) {
-            mWordIterator = new WordIterator(getLocale());
+            mWordIterator = new WordIterator(getTextServicesLocale());
         }
         return mWordIterator;
     }
@@ -10113,27 +10112,35 @@
             }
         }
 
-        final InputMethodManager imm = InputMethodManager.peekInstance();
-        boolean extractedTextModeWillBeStartedFullScreen = !(this instanceof ExtractEditText) &&
-                imm != null && imm.isFullscreenMode();
+        boolean willExtract = extractedTextModeWillBeStarted();
 
         // Do not start the action mode when extracted text will show up full screen, thus
         // immediately hiding the newly created action bar, which would be visually distracting.
-        if (!extractedTextModeWillBeStartedFullScreen) {
+        if (!willExtract) {
             ActionMode.Callback actionModeCallback = new SelectionActionModeCallback();
             mSelectionActionMode = startActionMode(actionModeCallback);
         }
-        final boolean selectionStarted = mSelectionActionMode != null ||
-                extractedTextModeWillBeStartedFullScreen;
 
-        if (selectionStarted && !mTextIsSelectable && imm != null && mSoftInputShownOnFocus) {
+        final boolean selectionStarted = mSelectionActionMode != null || willExtract;
+        if (selectionStarted && !mTextIsSelectable && mSoftInputShownOnFocus) {
             // Show the IME to be able to replace text, except when selecting non editable text.
-            imm.showSoftInput(this, 0, null);
+            final InputMethodManager imm = InputMethodManager.peekInstance();
+            if (imm != null) {
+                imm.showSoftInput(this, 0, null);
+            }
         }
 
         return selectionStarted;
     }
 
+    private boolean extractedTextModeWillBeStarted() {
+        if (!(this instanceof ExtractEditText)) {
+            final InputMethodManager imm = InputMethodManager.peekInstance();
+            return  imm != null && imm.isFullscreenMode();
+        }
+        return false;
+    }
+
     private void stopSelectionActionMode() {
         if (mSelectionActionMode != null) {
             // This will hide the mSelectionModifierCursorController
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 17b8acf..89f9d4e 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -25,14 +25,11 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
-import android.hardware.Camera;
-import android.hardware.Camera.CameraInfo;
 import android.os.FileObserver;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
-import android.os.SystemProperties;
 import android.os.storage.IMountService;
 import android.provider.Settings;
 import android.security.KeyStore;
@@ -41,7 +38,6 @@
 import android.util.Log;
 import android.view.View;
 import android.widget.Button;
-import android.widget.TextView;
 
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -968,6 +964,11 @@
                 com.android.internal.R.bool.config_enable_puk_unlock_screen);
     }
 
+    public boolean isEmergencyCallEnabledWhileSimLocked() {
+        return mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_enable_emergency_call_while_sim_locked);
+    }
+
     /**
      * @return A formatted string of the next alarm (for showing on the lock screen),
      *   or null if there is no next alarm.
@@ -1031,12 +1032,10 @@
      *  {@link TelephonyManager#CALL_STATE_IDLE}
      *  {@link TelephonyManager#CALL_STATE_RINGING}
      *  {@link TelephonyManager#CALL_STATE_OFFHOOK}
-     * @param showIfCapable indicates whether the button should be shown if emergency calls are
-     *                      possible on the device
+     * @param shown indicates whether the given screen wants the emergency button to show at all
      */
-    public void updateEmergencyCallButtonState(Button button, int  phoneState,
-            boolean showIfCapable) {
-        if (isEmergencyCallCapable() && showIfCapable) {
+    public void updateEmergencyCallButtonState(Button button, int  phoneState, boolean shown) {
+        if (isEmergencyCallCapable() && shown) {
             button.setVisibility(View.VISIBLE);
         } else {
             button.setVisibility(View.GONE);
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 1718e74..2bd4fa0 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -38,6 +38,7 @@
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
 #include <utils/threads.h>
+#include <utils/String8.h>
 
 #include <ScopedUtfChars.h>
 #include <ScopedLocalRef.h>
@@ -651,7 +652,8 @@
             gParcelFileDescriptorOffsets.mClass, gParcelFileDescriptorOffsets.mConstructor, fileDesc);
 }
 
-void signalExceptionForError(JNIEnv* env, jobject obj, status_t err)
+static void signalExceptionForError(JNIEnv* env, jobject obj, status_t err,
+        bool canThrowRemoteException = false)
 {
     switch (err) {
         case UNKNOWN_ERROR:
@@ -688,14 +690,25 @@
             jniThrowException(env, "java/lang/RuntimeException", "Item already exists");
             break;
         case DEAD_OBJECT:
-            jniThrowException(env, "android/os/DeadObjectException", NULL);
+            // DeadObjectException is a checked exception, only throw from certain methods.
+            jniThrowException(env, canThrowRemoteException
+                    ? "android/os/DeadObjectException"
+                            : "java/lang/RuntimeException", NULL);
             break;
         case UNKNOWN_TRANSACTION:
             jniThrowException(env, "java/lang/RuntimeException", "Unknown transaction code");
             break;
         case FAILED_TRANSACTION:
             LOGE("!!! FAILED BINDER TRANSACTION !!!");
-            //jniThrowException(env, "java/lang/OutOfMemoryError", "Binder transaction too large");
+            // TransactionTooLargeException is a checked exception, only throw from certain methods.
+            // FIXME: Transaction too large is the most common reason for FAILED_TRANSACTION
+            //        but it is not the only one.  The Binder driver can return BR_FAILED_REPLY
+            //        for other reasons also, such as if the transaction is malformed or
+            //        refers to an FD that has been closed.  We should change the driver
+            //        to enable us to distinguish these cases in the future.
+            jniThrowException(env, canThrowRemoteException
+                    ? "android/os/TransactionTooLargeException"
+                            : "java/lang/RuntimeException", NULL);
             break;
         case FDS_NOT_ALLOWED:
             jniThrowException(env, "java/lang/RuntimeException",
@@ -703,6 +716,12 @@
             break;
         default:
             LOGE("Unknown binder error code. 0x%x", err);
+            String8 msg;
+            msg.appendFormat("Unknown binder error code. 0x%x", err);
+            // RemoteException is a checked exception, only throw from certain methods.
+            jniThrowException(env, canThrowRemoteException
+                    ? "android/os/RemoteException" : "java/lang/RuntimeException", msg.string());
+            break;
     }
 }
 
@@ -1036,8 +1055,7 @@
 }
 
 static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
-                                                jint code, jobject dataObj,
-                                                jobject replyObj, jint flags)
+        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
 {
     if (dataObj == NULL) {
         jniThrowNullPointerException(env, NULL);
@@ -1084,12 +1102,12 @@
         return JNI_FALSE;
     }
 
-    signalExceptionForError(env, obj, err);
+    signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);
     return JNI_FALSE;
 }
 
 static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj,
-                                               jobject recipient, jint flags)
+        jobject recipient, jint flags) // throws RemoteException
 {
     if (recipient == NULL) {
         jniThrowNullPointerException(env, NULL);
@@ -1114,7 +1132,7 @@
             // Failure adding the death recipient, so clear its reference
             // now.
             jdr->clearReference();
-            signalExceptionForError(env, obj, err);
+            signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);
         }
     }
 }
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
old mode 100644
new mode 100755
index 8b07e34..767cafe
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -453,6 +453,11 @@
          If unlock screen is disabled, the puk should be unlocked through Emergency Dialer -->
     <bool name="config_enable_puk_unlock_screen">true</bool>
 
+    <!-- Enable emergency call when sim is locked or puk locked. Some countries/carriers do not
+         allow emergency calls to be placed without the IMSI, which is locked in the SIM.
+         If so, this should be set to 'false' in an overlay. -->
+    <bool name="config_enable_emergency_call_while_sim_locked">true</bool>
+
     <!-- Control the behavior when the user long presses the home button.
             0 - Nothing
             1 - Recent apps dialog
diff --git a/docs/html/resources/resources-data.js b/docs/html/resources/resources-data.js
index 237e18c..41a5a51 100644
--- a/docs/html/resources/resources-data.js
+++ b/docs/html/resources/resources-data.js
@@ -578,7 +578,7 @@
     }
   },
   {
-    tags: ['sample', 'newfeature', 'performance', 'gamedev', 'gl'],
+    tags: ['sample', 'newfeature', 'performance', 'gamedev', 'gl', 'updated'],
     path: 'samples/RenderScript/index.html',
     title: {
       en: 'RenderScript'
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 2f32bd8..fe15605 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -521,6 +521,9 @@
         ensureValidDirection(direction);
         ensureValidStreamType(streamType);
 
+        // use stream type alias here so that streams with same alias have the same behavior,
+        // including with regard to silent mode control (e.g the use of STREAM_RING below and in
+        // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION)
         int streamTypeAlias = STREAM_VOLUME_ALIAS[streamType];
         VolumeStreamState streamState = mStreamStates[streamTypeAlias];
         final int oldIndex = (streamState.muteCount() != 0) ? streamState.mLastAudibleIndex : streamState.mIndex;
@@ -529,9 +532,8 @@
         // If either the client forces allowing ringer modes for this adjustment,
         // or the stream type is one that is affected by ringer modes
         if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
-             (!mVoiceCapable && streamType != AudioSystem.STREAM_VOICE_CALL &&
-               streamType != AudioSystem.STREAM_BLUETOOTH_SCO) ||
-                (mVoiceCapable && streamTypeAlias == AudioSystem.STREAM_RING)) {
+                streamTypeAlias == AudioSystem.STREAM_RING ||
+                (!mVoiceCapable && streamTypeAlias == AudioSystem.STREAM_MUSIC)) {
             // do not vibrate if already in vibrate mode
             if (mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
                 flags &= ~AudioManager.FLAG_VIBRATE;
@@ -545,10 +547,19 @@
         int index;
         if (streamState.muteCount() != 0) {
             if (adjustVolume) {
-                streamState.adjustLastAudibleIndex(direction);
-                // Post a persist volume msg
-                sendMsg(mAudioHandler, MSG_PERSIST_VOLUME, streamType,
-                        SENDMSG_REPLACE, 0, 1, streamState, PERSIST_DELAY);
+                // adjust volume on all stream types sharing the same alias otherwise a query
+                // on last audible index for an alias would not give the correct value
+                int numStreamTypes = AudioSystem.getNumStreamTypes();
+                for (int i = numStreamTypes - 1; i >= 0; i--) {
+                    if (STREAM_VOLUME_ALIAS[i] == streamTypeAlias) {
+                        VolumeStreamState s = mStreamStates[i];
+
+                        s.adjustLastAudibleIndex(direction);
+                        // Post a persist volume msg
+                        sendMsg(mAudioHandler, MSG_PERSIST_VOLUME, i,
+                                SENDMSG_REPLACE, 0, 1, s, PERSIST_DELAY);
+                    }
+                }
             }
             index = streamState.mLastAudibleIndex;
         } else {
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
index ddced5f..aa07e57 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
@@ -421,8 +421,13 @@
 
         int32_t bufferSize = inHeader->nFilledLen;
 
+        // The PV decoder is lying to us, sometimes it'll claim to only have
+        // consumed a subset of the buffer when it clearly consumed all of it.
+        // ignore whatever it says...
+        int32_t tmp = bufferSize;
+
         if (PVDecodeVideoFrame(
-                    mHandle, &bitstream, &timestamp, &bufferSize,
+                    mHandle, &bitstream, &timestamp, &tmp,
                     &useExtTimestamp,
                     outHeader->pBuffer) != PV_TRUE) {
             LOGE("failed to decode video frame.");
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
index 740c957..dede3ac 100644
--- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
@@ -76,7 +76,8 @@
       mPicId(0),
       mHeadersDecoded(false),
       mEOSStatus(INPUT_DATA_AVAILABLE),
-      mOutputPortSettingsChange(NONE) {
+      mOutputPortSettingsChange(NONE),
+      mSignalledError(false) {
     initPorts();
     CHECK_EQ(initDecoder(), (status_t)OK);
 }
@@ -287,7 +288,7 @@
 }
 
 void SoftAVC::onQueueFilled(OMX_U32 portIndex) {
-    if (mOutputPortSettingsChange != NONE) {
+    if (mSignalledError || mOutputPortSettingsChange != NONE) {
         return;
     }
 
@@ -298,7 +299,6 @@
     List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
     List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
     H264SwDecRet ret = H264SWDEC_PIC_RDY;
-    status_t err = OK;
     bool portSettingsChanged = false;
     while ((mEOSStatus != INPUT_DATA_AVAILABLE || !inQueue.empty())
             && outQueue.size() == kNumOutputBuffers) {
@@ -372,7 +372,12 @@
                 inPicture.dataLen = 0;
                 if (ret < 0) {
                     LOGE("Decoder failed: %d", ret);
-                    err = ERROR_MALFORMED;
+
+                    notify(OMX_EventError, OMX_ErrorUndefined,
+                           ERROR_MALFORMED, NULL);
+
+                    mSignalledError = true;
+                    return;
                 }
             }
         }
@@ -400,10 +405,6 @@
             uint8_t *data = (uint8_t *) decodedPicture.pOutputPicture;
             drainOneOutputBuffer(picId, data);
         }
-
-        if (err != OK) {
-            notify(OMX_EventError, OMX_ErrorUndefined, err, NULL);
-        }
     }
 }
 
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.h b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
index 1cc85e8..879b014 100644
--- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
@@ -88,6 +88,8 @@
     };
     OutputPortSettingChange mOutputPortSettingsChange;
 
+    bool mSignalledError;
+
     void initPorts();
     status_t initDecoder();
     void updatePortDefinitions();
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index af7dd23..6a5efa4 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -44,12 +44,14 @@
 
 // If no access units are received within 5 secs, assume that the rtp
 // stream has ended and signal end of stream.
-static int64_t kAccessUnitTimeoutUs = 5000000ll;
+static int64_t kAccessUnitTimeoutUs = 10000000ll;
 
 // If no access units arrive for the first 10 secs after starting the
 // stream, assume none ever will and signal EOS or switch transports.
 static int64_t kStartupTimeoutUs = 10000000ll;
 
+static int64_t kDefaultKeepAliveTimeoutUs = 60000000ll;
+
 namespace android {
 
 static void MakeUserAgentString(AString *s) {
@@ -130,7 +132,9 @@
           mTryFakeRTCP(false),
           mReceivedFirstRTCPPacket(false),
           mReceivedFirstRTPPacket(false),
-          mSeekable(false) {
+          mSeekable(false),
+          mKeepAliveTimeoutUs(kDefaultKeepAliveTimeoutUs),
+          mKeepAliveGeneration(0) {
         mNetLooper->setName("rtsp net");
         mNetLooper->start(false /* runOnCallingThread */,
                           false /* canCallJava */,
@@ -371,6 +375,8 @@
 
             case 'disc':
             {
+                ++mKeepAliveGeneration;
+
                 int32_t reconnect;
                 if (msg->findInt32("reconnect", &reconnect) && reconnect) {
                     sp<AMessage> reply = new AMessage('conn', id());
@@ -502,6 +508,34 @@
                         CHECK_GE(i, 0);
 
                         mSessionID = response->mHeaders.valueAt(i);
+
+                        mKeepAliveTimeoutUs = kDefaultKeepAliveTimeoutUs;
+                        AString timeoutStr;
+                        if (GetAttribute(
+                                    mSessionID.c_str(), "timeout", &timeoutStr)) {
+                            char *end;
+                            unsigned long timeoutSecs =
+                                strtoul(timeoutStr.c_str(), &end, 10);
+
+                            if (end == timeoutStr.c_str() || *end != '\0') {
+                                LOGW("server specified malformed timeout '%s'",
+                                     timeoutStr.c_str());
+
+                                mKeepAliveTimeoutUs = kDefaultKeepAliveTimeoutUs;
+                            } else if (timeoutSecs < 15) {
+                                LOGW("server specified too short a timeout "
+                                     "(%lu secs), using default.",
+                                     timeoutSecs);
+
+                                mKeepAliveTimeoutUs = kDefaultKeepAliveTimeoutUs;
+                            } else {
+                                mKeepAliveTimeoutUs = timeoutSecs * 1000000ll;
+
+                                LOGI("server specified timeout of %lu secs.",
+                                     timeoutSecs);
+                            }
+                        }
+
                         i = mSessionID.find(";");
                         if (i >= 0) {
                             // Remove options, i.e. ";timeout=90"
@@ -555,6 +589,9 @@
                 if (index < mSessionDesc->countTracks()) {
                     setupTrack(index);
                 } else if (mSetupTracksSuccessful) {
+                    ++mKeepAliveGeneration;
+                    postKeepAlive();
+
                     AString request = "PLAY ";
                     request.append(mSessionURL);
                     request.append(" RTSP/1.0\r\n");
@@ -606,6 +643,51 @@
                 break;
             }
 
+            case 'aliv':
+            {
+                int32_t generation;
+                CHECK(msg->findInt32("generation", &generation));
+
+                if (generation != mKeepAliveGeneration) {
+                    // obsolete event.
+                    break;
+                }
+
+                AString request;
+                request.append("OPTIONS ");
+                request.append(mSessionURL);
+                request.append(" RTSP/1.0\r\n");
+                request.append("Session: ");
+                request.append(mSessionID);
+                request.append("\r\n");
+                request.append("\r\n");
+
+                sp<AMessage> reply = new AMessage('opts', id());
+                reply->setInt32("generation", mKeepAliveGeneration);
+                mConn->sendRequest(request.c_str(), reply);
+                break;
+            }
+
+            case 'opts':
+            {
+                int32_t result;
+                CHECK(msg->findInt32("result", &result));
+
+                LOGI("OPTIONS completed with result %d (%s)",
+                     result, strerror(-result));
+
+                int32_t generation;
+                CHECK(msg->findInt32("generation", &generation));
+
+                if (generation != mKeepAliveGeneration) {
+                    // obsolete event.
+                    break;
+                }
+
+                postKeepAlive();
+                break;
+            }
+
             case 'abor':
             {
                 for (size_t i = 0; i < mTracks.size(); ++i) {
@@ -952,6 +1034,12 @@
         }
     }
 
+    void postKeepAlive() {
+        sp<AMessage> msg = new AMessage('aliv', id());
+        msg->setInt32("generation", mKeepAliveGeneration);
+        msg->post((mKeepAliveTimeoutUs * 9) / 10);
+    }
+
     void postAccessUnitTimeoutCheck() {
         if (mCheckPending) {
             return;
@@ -1120,6 +1208,8 @@
     bool mReceivedFirstRTCPPacket;
     bool mReceivedFirstRTPPacket;
     bool mSeekable;
+    int64_t mKeepAliveTimeoutUs;
+    int32_t mKeepAliveGeneration;
 
     Vector<TrackInfo> mTracks;
 
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index aa40d58..522421b 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -34,6 +34,9 @@
 static const char* cacheFileMagic = "EGL$";
 static const size_t cacheFileHeaderSize = 8;
 
+// The time in seconds to wait before saving newly inserted cache entries.
+static const unsigned int deferredSaveDelay = 4;
+
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
@@ -128,6 +131,30 @@
     if (mInitialized) {
         sp<BlobCache> bc = getBlobCacheLocked();
         bc->set(key, keySize, value, valueSize);
+
+        if (!mSavePending) {
+            class DeferredSaveThread : public Thread {
+            public:
+                DeferredSaveThread() : Thread(false) {}
+
+                virtual bool threadLoop() {
+                    sleep(deferredSaveDelay);
+                    egl_cache_t* c = egl_cache_t::get();
+                    Mutex::Autolock lock(c->mMutex);
+                    if (c->mInitialized) {
+                        c->saveBlobCacheLocked();
+                    }
+                    c->mSavePending = false;
+                    return false;
+                }
+            };
+
+            // The thread will hold a strong ref to itself until it has finished
+            // running, so there's no need to keep a ref around.
+            sp<Thread> deferredSaveThread(new DeferredSaveThread());
+            mSavePending = true;
+            deferredSaveThread->run();
+        }
     }
 }
 
diff --git a/opengl/libs/EGL/egl_cache.h b/opengl/libs/EGL/egl_cache.h
index 05d5873..4389623 100644
--- a/opengl/libs/EGL/egl_cache.h
+++ b/opengl/libs/EGL/egl_cache.h
@@ -108,6 +108,13 @@
     // from disk.
     String8 mFilename;
 
+    // mSavePending indicates whether or not a deferred save operation is
+    // pending.  Each time a key/value pair is inserted into the cache via
+    // setBlob, a deferred save is initiated if one is not already pending.
+    // This will wait some amount of time and then trigger a save of the cache
+    // contents to disk.
+    bool mSavePending;
+
     // mMutex is the mutex used to prevent concurrent access to the member
     // variables. It must be locked whenever the member variables are accessed.
     mutable Mutex mMutex;
diff --git a/packages/SystemUI/res/drawable-hdpi/scrubber_control_disabled_holo.png b/packages/SystemUI/res/drawable-hdpi/scrubber_control_disabled_holo.png
deleted file mode 100644
index 55f6aa1..0000000
--- a/packages/SystemUI/res/drawable-hdpi/scrubber_control_disabled_holo.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/scrubber_control_holo.png b/packages/SystemUI/res/drawable-hdpi/scrubber_control_holo.png
deleted file mode 100644
index 19dae07..0000000
--- a/packages/SystemUI/res/drawable-hdpi/scrubber_control_holo.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/scrubber_track_holo_dark.9.png b/packages/SystemUI/res/drawable-hdpi/scrubber_track_holo_dark.9.png
deleted file mode 100644
index 8811df5..0000000
--- a/packages/SystemUI/res/drawable-hdpi/scrubber_track_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/scrubber_control_disabled_holo.png b/packages/SystemUI/res/drawable-mdpi/scrubber_control_disabled_holo.png
deleted file mode 100644
index 2b8768b..0000000
--- a/packages/SystemUI/res/drawable-mdpi/scrubber_control_disabled_holo.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/scrubber_control_holo.png b/packages/SystemUI/res/drawable-mdpi/scrubber_control_holo.png
deleted file mode 100644
index 0672564..0000000
--- a/packages/SystemUI/res/drawable-mdpi/scrubber_control_holo.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/scrubber_track_holo_dark.9.png b/packages/SystemUI/res/drawable-mdpi/scrubber_track_holo_dark.9.png
deleted file mode 100644
index 511d5c3..0000000
--- a/packages/SystemUI/res/drawable-mdpi/scrubber_track_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/notify_panel_clock_bg_normal.9.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/notify_panel_clock_bg_normal.9.png
index 60bd807..88137e8 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/notify_panel_clock_bg_normal.9.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/notify_panel_clock_bg_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/notify_panel_clock_bg_pressed.9.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/notify_panel_clock_bg_pressed.9.png
index 7fb5b20..6507a51 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/notify_panel_clock_bg_pressed.9.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/notify_panel_clock_bg_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/notify_panel_clock_bg_normal.9.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/notify_panel_clock_bg_normal.9.png
index 8354fef..798f589 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/notify_panel_clock_bg_normal.9.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/notify_panel_clock_bg_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/notify_panel_clock_bg_pressed.9.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/notify_panel_clock_bg_pressed.9.png
index f32980d..73247e5 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/notify_panel_clock_bg_pressed.9.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/notify_panel_clock_bg_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/notify_panel_clock_bg_normal.9.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/notify_panel_clock_bg_normal.9.png
index dbfce78..2b46c89 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/notify_panel_clock_bg_normal.9.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/notify_panel_clock_bg_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/notify_panel_clock_bg_pressed.9.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/notify_panel_clock_bg_pressed.9.png
index 37313e9..dd476b7 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/notify_panel_clock_bg_pressed.9.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/notify_panel_clock_bg_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/scrubber_control_disabled_holo.png b/packages/SystemUI/res/drawable-xhdpi/scrubber_control_disabled_holo.png
deleted file mode 100644
index 551c6dc..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/scrubber_control_disabled_holo.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/scrubber_control_holo.png b/packages/SystemUI/res/drawable-xhdpi/scrubber_control_holo.png
deleted file mode 100644
index 11f9c51..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/scrubber_control_holo.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/scrubber_track_holo_dark.9.png b/packages/SystemUI/res/drawable-xhdpi/scrubber_track_holo_dark.9.png
deleted file mode 100644
index b28dddf..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/scrubber_track_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ToggleSlider.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ToggleSlider.java
index 0eb2be6..fe2ec69 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ToggleSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ToggleSlider.java
@@ -80,10 +80,13 @@
         Drawable slider;
         final Resources res = getContext().getResources();
         if (checked) {
-            thumb = res.getDrawable(R.drawable.scrubber_control_disabled_holo);
-            slider = res.getDrawable(R.drawable.status_bar_settings_slider_disabled);
+            thumb = res.getDrawable(
+                    com.android.internal.R.drawable.scrubber_control_disabled_holo);
+            slider = res.getDrawable(
+                    R.drawable.status_bar_settings_slider_disabled);
         } else {
-            thumb = res.getDrawable(R.drawable.scrubber_control_holo);
+            thumb = res.getDrawable(
+                    com.android.internal.R.drawable.scrubber_control_selector_holo);
             slider = res.getDrawable(
                     com.android.internal.R.drawable.scrubber_progress_horizontal_holo_dark);
         }
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
index dafbdcf..a7da96e 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
@@ -91,7 +91,7 @@
     private LockPatternUtils mLockPatternUtils;
     private KeyguardUpdateMonitor mUpdateMonitor;
     private Button mEmergencyCallButton;
-    private boolean mUnlockDisabledDueToSimState;
+    private boolean mEmergencyButtonEnabledBecauseSimLocked;
 
     // Shadowed text values
     private CharSequence mCarrierText;
@@ -101,9 +101,10 @@
     private CharSequence mOwnerInfoText;
     private boolean mShowingStatus;
     private KeyguardScreenCallback mCallback;
-    private final boolean mShowEmergencyButtonByDefault;
+    private final boolean mEmergencyCallButtonEnabledInScreen;
     private CharSequence mPlmn;
     private CharSequence mSpn;
+    protected int mPhoneState;
 
     private class TransientTextManager {
         private TextView mTextView;
@@ -154,9 +155,17 @@
         }
     };
 
+    /**
+     *
+     * @param view the containing view of all widgets
+     * @param updateMonitor the update monitor to use
+     * @param lockPatternUtils lock pattern util object
+     * @param callback used to invoke emergency dialer
+     * @param emergencyButtonEnabledInScreen whether emergency button is enabled by default
+     */
     public KeyguardStatusViewManager(View view, KeyguardUpdateMonitor updateMonitor,
                 LockPatternUtils lockPatternUtils, KeyguardScreenCallback callback,
-                boolean showEmergencyButtonByDefault) {
+                boolean emergencyButtonEnabledInScreen) {
         if (DEBUG) Log.v(TAG, "KeyguardStatusViewManager()");
         mContainer = view;
         mDateFormatString = getContext().getString(R.string.full_wday_month_day_no_year);
@@ -171,7 +180,7 @@
         mOwnerInfoView = (TextView) findViewById(R.id.propertyOf);
         mTransportView = (TransportControlView) findViewById(R.id.transport);
         mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
-        mShowEmergencyButtonByDefault = showEmergencyButtonByDefault;
+        mEmergencyCallButtonEnabledInScreen = emergencyButtonEnabledInScreen;
 
         // Hide transport control view until we know we need to show it.
         if (mTransportView != null) {
@@ -452,12 +461,12 @@
      *
      * @param simState
      */
-    private void updateCarrierTextWithSimStatus(State simState) {
+    private void updateCarrierStateWithSimStatus(State simState) {
         if (DEBUG) Log.d(TAG, "updateCarrierTextWithSimStatus(), simState = " + simState);
 
         CharSequence carrierText = null;
         int carrierHelpTextId = 0;
-        mUnlockDisabledDueToSimState = false;
+        mEmergencyButtonEnabledBecauseSimLocked = false;
         mStatus = getStatusForIccState(simState);
         mSimState = simState;
         switch (mStatus) {
@@ -479,32 +488,35 @@
             case SimPermDisabled:
                 carrierText = getContext().getText(R.string.lockscreen_missing_sim_message_short);
                 carrierHelpTextId = R.string.lockscreen_permanent_disabled_sim_instructions;
-                mUnlockDisabledDueToSimState = true;
+                mEmergencyButtonEnabledBecauseSimLocked = true;
                 break;
 
             case SimMissingLocked:
                 carrierText = makeCarierString(mPlmn,
                         getContext().getText(R.string.lockscreen_missing_sim_message_short));
                 carrierHelpTextId = R.string.lockscreen_missing_sim_instructions;
-                mUnlockDisabledDueToSimState = true;
+                mEmergencyButtonEnabledBecauseSimLocked = true;
                 break;
 
             case SimLocked:
                 carrierText = makeCarierString(mPlmn,
                         getContext().getText(R.string.lockscreen_sim_locked_message));
+                mEmergencyButtonEnabledBecauseSimLocked = true;
                 break;
 
             case SimPukLocked:
                 carrierText = makeCarierString(mPlmn,
                         getContext().getText(R.string.lockscreen_sim_puk_locked_message));
                 if (!mLockPatternUtils.isPukUnlockScreenEnable()) {
-                    mUnlockDisabledDueToSimState = true;
+                    // This means we're showing the PUK unlock screen
+                    mEmergencyButtonEnabledBecauseSimLocked = true;
                 }
                 break;
         }
 
         setCarrierText(carrierText);
         setCarrierHelpText(carrierHelpTextId);
+        updateEmergencyCallButtonState(mPhoneState);
     }
 
     private View findViewById(int id) {
@@ -569,9 +581,12 @@
 
     private void updateEmergencyCallButtonState(int phoneState) {
         if (mEmergencyCallButton != null) {
-            boolean showIfCapable = mShowEmergencyButtonByDefault || mUnlockDisabledDueToSimState;
+            boolean enabledBecauseSimLocked =
+                    mLockPatternUtils.isEmergencyCallEnabledWhileSimLocked()
+                    && mEmergencyButtonEnabledBecauseSimLocked;
+            boolean shown = mEmergencyCallButtonEnabledInScreen || enabledBecauseSimLocked;
             mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton,
-                    phoneState, showIfCapable);
+                    phoneState, shown);
         }
     }
 
@@ -594,7 +609,7 @@
         public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
             mPlmn = plmn;
             mSpn = spn;
-            updateCarrierTextWithSimStatus(mSimState);
+            updateCarrierStateWithSimStatus(mSimState);
         }
 
         public void onRingerModeChanged(int state) {
@@ -602,6 +617,7 @@
         }
 
         public void onPhoneStateChanged(int phoneState) {
+            mPhoneState = phoneState;
             updateEmergencyCallButtonState(phoneState);
         }
 
@@ -618,7 +634,7 @@
     private SimStateCallback mSimStateCallback = new SimStateCallback() {
 
         public void onSimStateChanged(State simState) {
-            updateCarrierTextWithSimStatus(simState);
+            updateCarrierStateWithSimStatus(simState);
         }
     };
 
diff --git a/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java b/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
index 6acd1c5..47a7157 100644
--- a/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
@@ -106,7 +106,7 @@
         mHeaderText.setSelected(true);
 
         mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, updateMonitor,
-                lockpatternutils, callback, true);
+                lockpatternutils, callback, false);
 
         mPinText.setFocusableInTouchMode(true);
         mPinText.setOnFocusChangeListener(this);
diff --git a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java b/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
index 184748a..99e1ce1 100644
--- a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
@@ -100,7 +100,7 @@
         mOkButton.setOnClickListener(this);
 
         mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, updateMonitor,
-                lockpatternutils, callback, true);
+                lockpatternutils, callback, false);
 
         setFocusableInTouchMode(true);
     }
diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java
index b042da6..af9152d 100644
--- a/services/java/com/android/server/TextServicesManagerService.java
+++ b/services/java/com/android/server/TextServicesManagerService.java
@@ -40,6 +40,8 @@
 import android.service.textservice.SpellCheckerService;
 import android.text.TextUtils;
 import android.util.Slog;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
 import android.view.textservice.SpellCheckerInfo;
 import android.view.textservice.SpellCheckerSubtype;
 
@@ -222,20 +224,40 @@
             if (hashCode == 0 && !allowImplicitlySelectedSubtype) {
                 return null;
             }
-            final String systemLocale =
-                    mContext.getResources().getConfiguration().locale.toString();
+            String candidateLocale = null;
+            if (hashCode == 0) {
+                // Spell checker language settings == "auto"
+                final InputMethodManager imm =
+                        (InputMethodManager)mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
+                if (imm != null) {
+                    final InputMethodSubtype currentInputMethodSubtype =
+                            imm.getCurrentInputMethodSubtype();
+                    if (currentInputMethodSubtype != null) {
+                        final String localeString = currentInputMethodSubtype.getLocale();
+                        if (!TextUtils.isEmpty(localeString)) {
+                            // 1. Use keyboard locale if available in the spell checker
+                            candidateLocale = localeString;
+                        }
+                    }
+                }
+                if (candidateLocale == null) {
+                    // 2. Use System locale if available in the spell checker
+                    candidateLocale = mContext.getResources().getConfiguration().locale.toString();
+                }
+            }
             SpellCheckerSubtype candidate = null;
             for (int i = 0; i < sci.getSubtypeCount(); ++i) {
                 final SpellCheckerSubtype scs = sci.getSubtypeAt(i);
                 if (hashCode == 0) {
-                    if (systemLocale.equals(locale)) {
+                    if (candidateLocale.equals(locale)) {
                         return scs;
                     } else if (candidate == null) {
                         final String scsLocale = scs.getLocale();
-                        if (systemLocale.length() >= 2
+                        if (candidateLocale.length() >= 2
                                 && scsLocale.length() >= 2
-                                && systemLocale.substring(0, 2).equals(
+                                && candidateLocale.substring(0, 2).equals(
                                         scsLocale.substring(0, 2))) {
+                            // Fall back to the applicable language
                             candidate = scs;
                         }
                     }
@@ -244,9 +266,13 @@
                         Slog.w(TAG, "Return subtype " + scs.hashCode() + ", input= " + locale
                                 + ", " + scs.getLocale());
                     }
+                    // 3. Use the user specified spell check language
                     return scs;
                 }
             }
+            // 4. Fall back to the applicable language and return it if not null
+            // 5. Simply just return it even if it's null which means we could find no suitable
+            // spell check languages
             return candidate;
         }
     }
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index b916bd7..53502db 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -31,7 +31,7 @@
 endif
 
 ifneq (,$(findstring $(TARGET_DEVICE),tuna toro maguro))
-	LOCAL_CFLAGS += -DREFRESH_RATE=48
+	LOCAL_CFLAGS += -DREFRESH_RATE=59
 endif
 
 
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 410e961..6d9a2c2 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -213,7 +213,7 @@
     protected static final String NULL_IP = "0.0.0.0";
 
     // Default for the data stall alarm
-    protected static final int DATA_STALL_ALARM_DELAY_IN_MS_DEFAULT = 1000 * 60 * 3;
+    protected static final int DATA_STALL_ALARM_DELAY_IN_MS_DEFAULT = 1000 * 60 * 6;
     // If attempt is less than this value we're doing first level recovery
     protected static final int DATA_STALL_NO_RECV_POLL_LIMIT = 1;
     // Tag for tracking stale alarms
diff --git a/telephony/java/com/android/internal/telephony/cat/ComprehensionTlv.java b/telephony/java/com/android/internal/telephony/cat/ComprehensionTlv.java
index 99f662d..e5a2d31 100644
--- a/telephony/java/com/android/internal/telephony/cat/ComprehensionTlv.java
+++ b/telephony/java/com/android/internal/telephony/cat/ComprehensionTlv.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 The Android Open Source Project
+ * 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.
@@ -28,6 +28,7 @@
  * {@hide}
  */
 class ComprehensionTlv {
+    private static final String LOG_TAG = "ComprehensionTlv";
     private int mTag;
     private boolean mCr;
     private int mLength;
@@ -88,8 +89,13 @@
         int endIndex = data.length;
         while (startIndex < endIndex) {
             ComprehensionTlv ctlv = ComprehensionTlv.decode(data, startIndex);
-            items.add(ctlv);
-            startIndex = ctlv.mValueIndex + ctlv.mLength;
+            if (ctlv != null) {
+                items.add(ctlv);
+                startIndex = ctlv.mValueIndex + ctlv.mLength;
+            } else {
+                CatLog.d(LOG_TAG, "decodeMany: ctlv is null, stop decoding");
+                break;
+            }
         }
 
         return items;