Merge "Fix issue 2418668: AudioManager isWiredHeadsetOn() always returns false for headset without mic."
diff --git a/common/java/com/android/common/Base64.java b/common/java/com/android/common/Base64.java
index 772d567..d65e24e 100644
--- a/common/java/com/android/common/Base64.java
+++ b/common/java/com/android/common/Base64.java
@@ -51,6 +51,13 @@
      */
     public static final int WEB_SAFE = 8;
 
+    /**
+     * Flag to pass to Base64OutputStream to indicate that it should
+     * not close the output stream it is wrapping when it itself is
+     * closed.
+     */
+    public static final int NO_CLOSE = 16;
+
     //  --------------------------------------------------------
     //  decoding
     //  --------------------------------------------------------
diff --git a/common/java/com/android/common/Base64OutputStream.java b/common/java/com/android/common/Base64OutputStream.java
index 7c37428..76e1b6a 100644
--- a/common/java/com/android/common/Base64OutputStream.java
+++ b/common/java/com/android/common/Base64OutputStream.java
@@ -29,6 +29,7 @@
     private final boolean encode;
     private final Base64.EncoderState estate;
     private final Base64.DecoderState dstate;
+    private final int flags;
 
     private byte[] buffer = null;
     private int bpos = 0;
@@ -59,6 +60,7 @@
      */
     public Base64OutputStream(OutputStream out, int flags, boolean encode) {
         super(out);
+        this.flags = flags;
         this.encode = encode;
         if (encode) {
             estate = new Base64.EncoderState(flags, null);
@@ -106,7 +108,11 @@
     public void close() throws IOException {
         flushBuffer();
         internalWrite(EMPTY, 0, 0, true);
-        out.close();
+        if ((flags & Base64.NO_CLOSE) == 0) {
+            out.close();
+        } else {
+            out.flush();
+        }
     }
 
     /**
diff --git a/core/java/android/speech/RecognitionManager.java b/core/java/android/speech/RecognitionManager.java
index 74b9fce..7f55ad6 100644
--- a/core/java/android/speech/RecognitionManager.java
+++ b/core/java/android/speech/RecognitionManager.java
@@ -171,7 +171,7 @@
      */
     public static boolean isRecognitionAvailable(final Context context) {
         final List<ResolveInfo> list = context.getPackageManager().queryIntentServices(
-                new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);
+                new Intent(RecognitionService.SERVICE_INTERFACE), 0);
         return list != null && list.size() != 0;
     }
 
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index b0233ab..6c7cd71 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -213,8 +213,6 @@
     // true means redraw the screen all-the-time. Only with AUTO_REDRAW_HACK
     private boolean mAutoRedraw;
     private int mRootLayer; // C++ pointer to the root layer
-    private boolean mLayersHaveAnimations;
-    private EvaluateLayersAnimations mEvaluateThread;
 
     static final String LOGTAG = "webview";
 
@@ -3072,6 +3070,15 @@
             int scrollY = computeVerticalScrollOffset();
             int viewHeight = getHeight() - getVisibleTitleHeight();
 
+            // Currently for each draw we compute the animation values;
+            // We may in the future decide to do that independently.
+            if (nativeEvaluateLayersAnimations(mRootLayer)) {
+                // If we have unfinished (or unstarted) animations,
+                // we ask for a repaint.
+                invalidate();
+            }
+
+            // We can now draw the layers.
             nativeDrawLayers(mRootLayer, mScrollX, scrollY,
                              getWidth(), viewHeight,
                              mActualScale, canvas);
@@ -3415,40 +3422,6 @@
     }
 
     /*
-     * This class runs the layers animations in their own thread,
-     * so that we do not slow down the UI.
-     */
-    private class EvaluateLayersAnimations extends Thread {
-        boolean mRunning = true;
-        // delay corresponds to 40fps, no need to go faster.
-        int mDelay = 25; // in ms
-        public void run() {
-            while (mRunning) {
-                if (mLayersHaveAnimations && mRootLayer != 0) {
-                    // updates is a C++ pointer to a Vector of AnimationValues
-                    int updates = nativeEvaluateLayersAnimations(mRootLayer);
-                    if (updates == 0) {
-                        mRunning = false;
-                    }
-                    Message.obtain(mPrivateHandler,
-                          WebView.IMMEDIATE_REPAINT_MSG_ID,
-                          updates, 0).sendToTarget();
-                } else {
-                    mRunning = false;
-                }
-                try {
-                    Thread.currentThread().sleep(mDelay);
-                } catch (InterruptedException e) {
-                    mRunning = false;
-                }
-            }
-        }
-        public void cancel() {
-            mRunning = false;
-        }
-    }
-
-    /*
      * This class requests an Adapter for the WebTextView which shows past
      * entries stored in the database.  It is a Runnable so that it can be done
      * in its own thread, without slowing down the UI.
@@ -5929,13 +5902,6 @@
                     break;
                 }
                 case IMMEDIATE_REPAINT_MSG_ID: {
-                    int updates = msg.arg1;
-                    if (updates != 0) {
-                        // updates is a C++ pointer to a Vector of
-                        // AnimationValues that we apply to the layers.
-                        // The Vector is deallocated in nativeUpdateLayers().
-                        nativeUpdateLayers(updates);
-                    }
                     invalidate();
                     break;
                 }
@@ -5945,18 +5911,6 @@
                     if (oldLayer > 0) {
                         nativeDestroyLayer(oldLayer);
                     }
-                    if (mRootLayer == 0) {
-                        mLayersHaveAnimations = false;
-                    }
-                    if (mEvaluateThread != null) {
-                        mEvaluateThread.cancel();
-                        mEvaluateThread = null;
-                    }
-                    if (nativeLayersHaveAnimations(mRootLayer)) {
-                        mLayersHaveAnimations = true;
-                        mEvaluateThread = new EvaluateLayersAnimations();
-                        mEvaluateThread.start();
-                    }
                     invalidate();
                     break;
                 }
@@ -6729,9 +6683,7 @@
     private native void     nativeDestroy();
     private native void     nativeDrawCursorRing(Canvas content);
     private native void     nativeDestroyLayer(int layer);
-    private native int      nativeEvaluateLayersAnimations(int layer);
-    private native boolean  nativeLayersHaveAnimations(int layer);
-    private native void     nativeUpdateLayers(int updates);
+    private native boolean  nativeEvaluateLayersAnimations(int layer);
     private native void     nativeDrawLayers(int layer,
                                              int scrollX, int scrollY,
                                              int width, int height,
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index 742a7d8..c907368 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -21,6 +21,7 @@
 import android.app.IActivityManager;
 import android.app.IUiModeManager;
 import android.app.KeyguardManager;
+import android.app.StatusBarManager;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.content.ActivityNotFoundException;
@@ -71,6 +72,8 @@
     private boolean mKeyguardDisabled;
     private LockPatternUtils mLockPatternUtils;
 
+    private StatusBarManager mStatusBarManager;    
+
     // The broadcast receiver which receives the result of the ordered broadcast sent when
     // the dock state changes. The original ordered broadcast is sent with an initial result
     // code of RESULT_OK. If any of the registered broadcast receivers changes this value, e.g.,
@@ -234,6 +237,21 @@
             // Disabling the car mode clears the night mode.
             setMode(Configuration.UI_MODE_TYPE_NORMAL, MODE_NIGHT_NO);
         }
+
+        if (mStatusBarManager == null) {
+            mStatusBarManager = (StatusBarManager) mContext.getSystemService(Context.STATUS_BAR_SERVICE);
+        }
+
+        // Fear not: StatusBarService manages a list of requests to disable
+        // features of the status bar; these are ORed together to form the
+        // active disabled list. So if (for example) the device is locked and
+        // the status bar should be totally disabled, the calls below will
+        // have no effect until the device is unlocked.
+        if (mStatusBarManager != null) {
+            mStatusBarManager.disable(enabled 
+                ? StatusBarManager.DISABLE_NOTIFICATION_TICKER
+                : StatusBarManager.DISABLE_NONE);
+        }
     }
 
     private void setMode(int modeType, int modeNight) throws RemoteException {