Merge "MountService: Send ACTION_MEDIA_UNSHARED Intent a volume is no longer shared via UMS."
diff --git a/api/current.xml b/api/current.xml
index be38d49..1f7be9e 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -24473,6 +24473,17 @@
  visibility="public"
 >
 </field>
+<field name="SUGGEST_COLUMN_TEXT_2_URL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;suggest_text_2_url&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="SUGGEST_MIME_TYPE"
  type="java.lang.String"
  transient="false"
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index b54e53d..67f9629 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -1355,6 +1355,16 @@
      *  a much smaller appearance.
      */
     public final static String SUGGEST_COLUMN_TEXT_2 = "suggest_text_2";
+
+    /**
+     * Column name for suggestions cursor.  <i>Optional.</i> This is a URL that will be shown
+     * as the second line of text instead of {@link #SUGGEST_COLUMN_TEXT_2}. This is a separate
+     * column so that the search UI knows to display the text as a URL, e.g. by using a different
+     * color. If this column is absent, or has the value {@code null},
+     * {@link #SUGGEST_COLUMN_TEXT_2} will be used instead.
+     */
+    public final static String SUGGEST_COLUMN_TEXT_2_URL = "suggest_text_2_url";
+
     /**
      * Column name for suggestions cursor.  <i>Optional.</i>  If your cursor includes this column,
      *  then all suggestions will be provided in a format that includes space for two small icons,
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index 57795d1..07e9793 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -16,6 +16,8 @@
 
 package android.app;
 
+import com.android.internal.R;
+
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -23,16 +25,20 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.StateListDrawable;
 import android.net.Uri;
-import android.text.Html;
+import android.text.Spannable;
+import android.text.SpannableString;
 import android.text.TextUtils;
+import android.text.style.TextAppearanceSpan;
 import android.util.Log;
 import android.util.SparseArray;
+import android.util.TypedValue;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Filter;
@@ -64,10 +70,13 @@
     private SparseArray<Drawable.ConstantState> mBackgroundsCache;
     private boolean mClosed = false;
 
+    // URL color
+    private ColorStateList mUrlColor;
+
     // Cached column indexes, updated when the cursor changes.
-    private int mFormatCol;
     private int mText1Col;
     private int mText2Col;
+    private int mText2UrlCol;
     private int mIconName1Col;
     private int mIconName2Col;
     private int mBackgroundColorCol;
@@ -188,9 +197,9 @@
             super.changeCursor(c);
 
             if (c != null) {
-                mFormatCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_FORMAT);
                 mText1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1);
                 mText2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2);
+                mText2UrlCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2_URL);
                 mIconName1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1);
                 mIconName2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2);
                 mBackgroundColorCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_BACKGROUND_COLOR);
@@ -239,9 +248,20 @@
         Drawable background = getItemBackground(backgroundColor);
         view.setBackgroundDrawable(background);
 
-        final boolean isHtml = mFormatCol > 0 && "html".equals(cursor.getString(mFormatCol));
-        setViewText(cursor, views.mText1, mText1Col, isHtml);
-        setViewText(cursor, views.mText2, mText2Col, isHtml);
+        if (views.mText1 != null) {
+            String text1 = getStringOrNull(cursor, mText1Col);
+            setViewText(views.mText1, text1);
+        }
+        if (views.mText2 != null) {
+            // First check TEXT_2_URL
+            CharSequence text2 = getStringOrNull(cursor, mText2UrlCol);
+            if (text2 != null) {
+                text2 = formatUrl(text2);
+            } else {
+                text2 = getStringOrNull(cursor, mText2Col);
+            }
+            setViewText(views.mText2, text2);
+        }
 
         if (views.mIcon1 != null) {
             setViewDrawable(views.mIcon1, getIcon1(cursor));
@@ -251,6 +271,21 @@
         }
     }
 
+    private CharSequence formatUrl(CharSequence url) {
+        if (mUrlColor == null) {
+            // Lazily get the URL color from the current theme.
+            TypedValue colorValue = new TypedValue();
+            mContext.getTheme().resolveAttribute(R.attr.textColorSearchUrl, colorValue, true);
+            mUrlColor = mContext.getResources().getColorStateList(colorValue.resourceId);
+        }
+
+        SpannableString text = new SpannableString(url);
+        text.setSpan(new TextAppearanceSpan(null, 0, 0, mUrlColor, null),
+                0, url.length(),
+                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+        return text;
+    }
+
     /**
      * Gets a drawable with no color when selected or pressed, and the given color when
      * neither selected nor pressed.
@@ -278,19 +313,7 @@
         }
     }
 
-    private void setViewText(Cursor cursor, TextView v, int textCol, boolean isHtml) {
-        if (v == null) {
-            return;
-        }
-        CharSequence text = null;
-        if (textCol >= 0) {
-            String str = cursor.getString(textCol);
-            if (isHtml && looksLikeHtml(str)) {
-                text = Html.fromHtml(str);
-            } else {
-                text = str;
-            }
-        }
+    private void setViewText(TextView v, CharSequence text) {
         // Set the text even if it's null, since we need to clear any previous text.
         v.setText(text);
 
@@ -301,15 +324,6 @@
         }
     }
 
-    private static boolean looksLikeHtml(String str) {
-        if (TextUtils.isEmpty(str)) return false;
-        for (int i = str.length() - 1; i >= 0; i--) {
-            char c = str.charAt(i);
-            if (c == '<' || c == '&') return true;
-        }
-        return false;
-    }
-
     private Drawable getIcon1(Cursor cursor) {
         if (mIconName1Col < 0) {
             return null;
@@ -617,6 +631,10 @@
      */
     public static String getColumnString(Cursor cursor, String columnName) {
         int col = cursor.getColumnIndex(columnName);
+        return getStringOrNull(cursor, col);
+    }
+
+    private static String getStringOrNull(Cursor cursor, int col) {
         if (col == NONE) {
             return null;
         }
@@ -629,5 +647,4 @@
             return null;
         }
     }
-
 }
diff --git a/core/java/android/database/CursorToBulkCursorAdaptor.java b/core/java/android/database/CursorToBulkCursorAdaptor.java
index 19ad946..748eb99 100644
--- a/core/java/android/database/CursorToBulkCursorAdaptor.java
+++ b/core/java/android/database/CursorToBulkCursorAdaptor.java
@@ -143,8 +143,7 @@
 
     public void close() {
         maybeUnregisterObserverProxy();
-        mCursor.deactivate();       
-        
+        mCursor.close();
     }
 
     public int requery(IContentObserver observer, CursorWindow window) {
diff --git a/core/java/android/database/sqlite/DatabaseObjectNotClosedException.java b/core/java/android/database/sqlite/DatabaseObjectNotClosedException.java
new file mode 100644
index 0000000..8ac4c0f
--- /dev/null
+++ b/core/java/android/database/sqlite/DatabaseObjectNotClosedException.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.database.sqlite;
+
+/**
+ * An exception that indicates that garbage-collector is finalizing a database object
+ * that is not explicitly closed
+ * @hide
+ */
+public class DatabaseObjectNotClosedException extends RuntimeException
+{
+    private static final String s = "Application did not close the cursor or database object " +
+            "that was opened here";
+
+    public DatabaseObjectNotClosedException()
+    {
+        super(s);
+    }
+}
diff --git a/core/java/android/database/sqlite/SQLiteCompiledSql.java b/core/java/android/database/sqlite/SQLiteCompiledSql.java
index 486ad20..4ccf6b0 100644
--- a/core/java/android/database/sqlite/SQLiteCompiledSql.java
+++ b/core/java/android/database/sqlite/SQLiteCompiledSql.java
@@ -56,7 +56,7 @@
     /* package */ SQLiteCompiledSql(SQLiteDatabase db, String sql) {
         mDatabase = db;
         mSqlStmt = sql;
-        mStackTrace = new Exception().fillInStackTrace();
+        mStackTrace = new DatabaseObjectNotClosedException().fillInStackTrace();
         this.nHandle = db.mNativeHandle;
         compile(sql, true);
     }
diff --git a/core/java/android/database/sqlite/SQLiteCursor.java b/core/java/android/database/sqlite/SQLiteCursor.java
index 96ed297..3f0fcb1 100644
--- a/core/java/android/database/sqlite/SQLiteCursor.java
+++ b/core/java/android/database/sqlite/SQLiteCursor.java
@@ -207,7 +207,7 @@
             String editTable, SQLiteQuery query) {
         // The AbstractCursor constructor needs to do some setup.
         super();
-        mStackTrace = new Exception().fillInStackTrace();
+        mStackTrace = new DatabaseObjectNotClosedException().fillInStackTrace();
         mDatabase = db;
         mDriver = driver;
         mEditTable = editTable;
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index d8ccf85..9fa9368 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -1749,7 +1749,7 @@
         mFlags = flags;
         mPath = path;
         mSlowQueryThreshold = SystemProperties.getInt(LOG_SLOW_QUERIES_PROPERTY, -1);
-        mStackTrace = new Exception().fillInStackTrace();
+        mStackTrace = new DatabaseObjectNotClosedException().fillInStackTrace();
         mFactory = factory;
         dbopen(mPath, mFlags);
         if (SQLiteDebug.DEBUG_SQL_CACHE) {
diff --git a/core/java/android/net/http/HttpsConnection.java b/core/java/android/net/http/HttpsConnection.java
index f735f3d..a67fd9a 100644
--- a/core/java/android/net/http/HttpsConnection.java
+++ b/core/java/android/net/http/HttpsConnection.java
@@ -59,7 +59,7 @@
     private static SSLSocketFactory mSslSocketFactory = null;
 
     static {
-        // This intiialization happens in the zygote. It triggers some
+        // This initialization happens in the zygote. It triggers some
         // lazy initialization that can will benefit later invocations of
         // initializeEngine().
         initializeEngine(null);
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index b28cf43..f363828 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -274,9 +274,11 @@
 
     private void onDeviceRemoved(String deviceObjectPath) {
         String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath);
-        if (address != null)
+        if (address != null) {
             mBluetoothService.getBondState().setBondState(address.toUpperCase(),
                     BluetoothDevice.BOND_NONE, BluetoothDevice.UNBOND_REASON_REMOVED);
+            mBluetoothService.setRemoteDeviceProperty(address, "UUIDs", null);
+        }
     }
 
     /*package*/ void onPropertyChanged(String[] propValues) {
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index db19bca..39edcad 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -822,8 +822,9 @@
                 break;
             case 1: // TEXT_AREA
                 single = false;
-                inputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE
+                inputType = EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE
                         | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES
+                        | EditorInfo.TYPE_CLASS_TEXT
                         | EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT;
                 imeOptions |= EditorInfo.IME_ACTION_NONE;
                 break;
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 72791fb..0739735 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2480,20 +2480,30 @@
      */
     public int findAll(String find) {
         if (0 == mNativeClass) return 0; // client isn't initialized
-        if (mFindIsUp == false) {
-            recordNewContentSize(mContentWidth, mContentHeight + mFindHeight,
-                    false);
-            mFindIsUp = true;
-        }
-        int result = nativeFindAll(find.toLowerCase(), find.toUpperCase());
+        int result = find != null ? nativeFindAll(find.toLowerCase(),
+                find.toUpperCase()) : 0;
         invalidate();
         mLastFind = find;
         return result;
     }
 
+    /**
+     * @hide
+     */
+    public void setFindIsUp(boolean isUp) {
+        mFindIsUp = isUp;
+        if (isUp) {
+            recordNewContentSize(mContentWidth, mContentHeight + mFindHeight,
+                    false);
+        }
+        if (0 == mNativeClass) return; // client isn't initialized
+        nativeSetFindIsUp(isUp);
+    }
+
     // Used to know whether the find dialog is open.  Affects whether
     // or not we draw the highlights for matches.
     private boolean mFindIsUp;
+
     private int mFindHeight;
     // Keep track of the last string sent, so we can search again after an
     // orientation change or the dismissal of the soft keyboard.
@@ -2553,14 +2563,21 @@
      * Clear the highlighting surrounding text matches created by findAll.
      */
     public void clearMatches() {
+        mLastFind = "";
         if (mNativeClass == 0)
             return;
-        if (mFindIsUp) {
-            recordNewContentSize(mContentWidth, mContentHeight - mFindHeight,
-                    false);
-            mFindIsUp = false;
-        }
-        nativeSetFindIsUp();
+        nativeSetFindIsEmpty();
+        invalidate();
+    }
+
+    /**
+     * @hide
+     */
+    public void notifyFindDialogDismissed() {
+        clearMatches();
+        setFindIsUp(false);
+        recordNewContentSize(mContentWidth, mContentHeight - mFindHeight,
+                false);
         // Now that the dialog has been removed, ensure that we scroll to a
         // location that is not beyond the end of the page.
         pinScrollTo(mScrollX, mScrollY, false, 0);
@@ -4477,12 +4494,12 @@
             y = getViewHeightWithTitle() - 1;
         }
 
-        // pass the touch events from UI thread to WebCore thread
-        if (mForwardTouchEvents
-                && (action != MotionEvent.ACTION_MOVE || eventTime
-                        - mLastSentTouchTime > mCurrentTouchInterval)
-                && (action == MotionEvent.ACTION_DOWN
-                        || mPreventDrag != PREVENT_DRAG_CANCEL)) {
+        // pass the touch events, except ACTION_MOVE which will be handled
+        // later, from UI thread to WebCore thread
+        if (mFullScreenHolder != null || (mForwardTouchEvents
+                && action != MotionEvent.ACTION_MOVE
+                && (action == MotionEvent.ACTION_DOWN || mPreventDrag
+                        != PREVENT_DRAG_CANCEL))) {
             WebViewCore.TouchEventData ted = new WebViewCore.TouchEventData();
             ted.mAction = action;
             ted.mX = viewToContentX((int) x + mScrollX);
@@ -4573,6 +4590,21 @@
                     if ((deltaX * deltaX + deltaY * deltaY) < mTouchSlopSquare) {
                         break;
                     }
+
+                    // pass the first ACTION_MOVE from UI thread to WebCore
+                    // thread after the distance is confirmed that it is a drag
+                    if (mFullScreenHolder == null && mForwardTouchEvents
+                            && mPreventDrag != PREVENT_DRAG_CANCEL) {
+                        WebViewCore.TouchEventData ted = new WebViewCore.TouchEventData();
+                        ted.mAction = action;
+                        ted.mX = viewToContentX((int) x + mScrollX);
+                        ted.mY = viewToContentY((int) y + mScrollY);
+                        ted.mEventTime = eventTime;
+                        ted.mMetaState = ev.getMetaState();
+                        mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
+                        mLastSentTouchTime = eventTime;
+                    }
+
                     if (mPreventDrag == PREVENT_DRAG_MAYBE_YES) {
                         // track mLastTouchTime as we may need to do fling at
                         // ACTION_UP
@@ -4629,6 +4661,20 @@
                                     Toast.LENGTH_LONG).show();
                         }
                     }
+                } else {
+                    // pass the touch events from UI thread to WebCore thread
+                    if (mFullScreenHolder == null && mForwardTouchEvents
+                            && eventTime - mLastSentTouchTime > mCurrentTouchInterval
+                            && mPreventDrag != PREVENT_DRAG_CANCEL) {
+                        WebViewCore.TouchEventData ted = new WebViewCore.TouchEventData();
+                        ted.mAction = action;
+                        ted.mX = viewToContentX((int) x + mScrollX);
+                        ted.mY = viewToContentY((int) y + mScrollY);
+                        ted.mEventTime = eventTime;
+                        ted.mMetaState = ev.getMetaState();
+                        mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
+                        mLastSentTouchTime = eventTime;
+                    }
                 }
 
                 // do pan
@@ -6863,7 +6909,8 @@
     private native void     nativeRecordButtons(boolean focused,
             boolean pressed, boolean invalidate);
     private native void     nativeSelectBestAt(Rect rect);
-    private native void     nativeSetFindIsUp();
+    private native void     nativeSetFindIsEmpty();
+    private native void     nativeSetFindIsUp(boolean isUp);
     private native void     nativeSetFollowedLink(boolean followed);
     private native void     nativeSetHeightCanMeasure(boolean measure);
     private native void     nativeSetRootLayer(int layer);
diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java
index 1730a68..8469c8b 100644
--- a/core/java/android/widget/OverScroller.java
+++ b/core/java/android/widget/OverScroller.java
@@ -418,6 +418,12 @@
      */
     public void setFinalX(int newX) {
         if (mScrollMode == MODE_DEFAULT) {
+            if (newX < mMinimumX) {
+                mMinimumX = newX;
+            }
+            if (newX > mMaximumX) {
+                mMaximumX = newX;
+            }
             mDefaultScroller.setFinalX(newX);
         }
     }
@@ -431,6 +437,12 @@
      */
     public void setFinalY(int newY) {
         if (mScrollMode == MODE_DEFAULT) {
+            if (newY < mMinimumY) {
+                mMinimumY = newY;
+            }
+            if (newY > mMaximumY) {
+                mMaximumY = newY;
+            }
             mDefaultScroller.setFinalY(newY);
         }
     }
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 1b5b3e4..02961f0 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -87,7 +87,7 @@
     </string-array>
 
     <!-- Regex array of allowable upstream ifaces for tethering - for example if you want
-         tethering on your a new interface called "foo2" add "foo\\d" here -->
+         tethering on a new interface called "foo2" add <item>"foo\\d"</item> to the array -->
     <string-array translatable="false" name="config_tether_upstream_regexs">
     </string-array>
 
diff --git a/core/tests/coretests/src/android/text/StaticLayoutTest.java b/core/tests/coretests/src/android/text/StaticLayoutTest.java
index 7511ec1..1f58a2c 100644
--- a/core/tests/coretests/src/android/text/StaticLayoutTest.java
+++ b/core/tests/coretests/src/android/text/StaticLayoutTest.java
@@ -26,6 +26,11 @@
 
 /**
  * Tests StaticLayout vertical metrics behavior.
+ * 
+ * Requires disabling access checks in the vm since this calls package-private
+ * APIs.
+ * 
+ * @Suppress
  */
 public class StaticLayoutTest extends TestCase {
 
@@ -33,7 +38,7 @@
      * Basic test showing expected behavior and relationship between font
      * metrics and line metrics.
      */
-    @SmallTest
+    //@SmallTest
     public void testGetters1() {
         LayoutBuilder b = builder();
         FontMetricsInt fmi = b.paint.getFontMetricsInt();
@@ -59,7 +64,7 @@
      * Basic test showing effect of includePad = true with 1 line.
      * Top and bottom padding are affected, as is the line descent and height.
      */
-    @SmallTest
+    //@SmallTest
     public void testGetters2() {
         LayoutBuilder b = builder()
             .setIncludePad(true);
@@ -74,7 +79,7 @@
      * Basic test showing effect of includePad = true wrapping to 2 lines.
      * Ascent of top line and descent of bottom line are affected.
      */
-    @SmallTest
+    //@SmallTest
     public void testGetters3() {
         LayoutBuilder b = builder()
             .setIncludePad(true)
@@ -91,7 +96,7 @@
      * Basic test showing effect of includePad = true wrapping to 3 lines.
      * First line ascent is top, bottom line descent is bottom.
      */
-    @SmallTest
+    //@SmallTest
     public void testGetters4() {
         LayoutBuilder b = builder()
             .setText("This is a longer test")
@@ -111,7 +116,7 @@
      * large text. See effect of leading. Currently, we don't expect there to
      * even be non-zero leading.
      */
-    @SmallTest
+    //@SmallTest
     public void testGetters5() {
         LayoutBuilder b = builder()
             .setText("This is a longer test")
@@ -138,7 +143,7 @@
      * Basic test showing effect of includePad = true, spacingAdd = 2, wrapping
      * to 3 lines.
      */
-    @SmallTest
+    //@SmallTest
     public void testGetters6() {
         int spacingAdd = 2; // int so expressions return int
         LayoutBuilder b = builder()
@@ -159,7 +164,7 @@
      * Basic test showing effect of includePad = true, spacingAdd = 2,
      * spacingMult = 1.5, wrapping to 3 lines.
      */
-    @SmallTest
+    //@SmallTest
     public void testGetters7() {
         LayoutBuilder b = builder()
             .setText("This is a longer test")
@@ -181,7 +186,7 @@
      * Basic test showing effect of includePad = true, spacingAdd = 0,
      * spacingMult = 0.8 when wrapping to 3 lines.
      */
-    @SmallTest
+    //@SmallTest
     public void testGetters8() {
         LayoutBuilder b = builder()
             .setText("This is a longer test")
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
index c4d4f99..57192a5 100644
--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -604,8 +604,11 @@
 
     // figure out the kinds of events the device reports
     
-    // See if this is a keyboard, and classify it.
-    uint8_t key_bitmask[(KEY_MAX+1)/8];
+    // See if this is a keyboard, and classify it.  Note that we only
+    // consider up through the function keys; we don't want to include
+    // ones after that (play cd etc) so we don't mistakenly consider a
+    // controller to be a keyboard.
+    uint8_t key_bitmask[(KEY_PLAYCD+1)/8];
     memset(key_bitmask, 0, sizeof(key_bitmask));
     LOGV("Getting keys...");
     if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {
@@ -702,22 +705,20 @@
         device->layoutMap->load(keylayoutFilename);
 
         // tell the world about the devname (the descriptive name)
-        int32_t publicID;
-        if (!mHaveFirstKeyboard && !defaultKeymap) {
-            publicID = 0;
+        if (!mHaveFirstKeyboard && !defaultKeymap && strstr(name, "-keypad")) {
             // the built-in keyboard has a well-known device ID of 0,
             // this device better not go away.
             mHaveFirstKeyboard = true;
             mFirstKeyboardId = device->id;
+            property_set("hw.keyboards.0.devname", name);
         } else {
-            publicID = device->id;
             // ensure mFirstKeyboardId is set to -something-.
             if (mFirstKeyboardId == 0) {
                 mFirstKeyboardId = device->id;
             }
         }
         char propName[100];
-        sprintf(propName, "hw.keyboards.%u.devname", publicID);
+        sprintf(propName, "hw.keyboards.%u.devname", device->id);
         property_set(propName, name);
 
         // 'Q' key support = cheap test of whether this is an alpha-capable kbd
@@ -734,8 +735,8 @@
             device->classes |= CLASS_DPAD;
         }
         
-        LOGI("New keyboard: publicID=%d device->id=0x%x devname='%s' propName='%s' keylayout='%s'\n",
-                publicID, device->id, name, propName, keylayoutFilename);
+        LOGI("New keyboard: device->id=0x%x devname='%s' propName='%s' keylayout='%s'\n",
+                device->id, name, propName, keylayoutFilename);
     }
 
     LOGI("New device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
@@ -808,18 +809,15 @@
             device->next = mClosingDevices;
             mClosingDevices = device;
 
-            uint32_t publicID;
             if (device->id == mFirstKeyboardId) {
                 LOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
                         device->path.string(), mFirstKeyboardId);
                 mFirstKeyboardId = 0;
-                publicID = 0;
-            } else {
-                publicID = device->id;
+                property_set("hw.keyboards.0.devname", NULL);
             }
             // clear the property
             char propName[100];
-            sprintf(propName, "hw.keyboards.%u.devname", publicID);
+            sprintf(propName, "hw.keyboards.%u.devname", device->id);
             property_set(propName, NULL);
             return 0;
         }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
index 88e171d..a3bbb74 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
@@ -20,8 +20,11 @@
 import com.android.mediaframeworktest.MediaNames;
 
 import android.database.sqlite.SQLiteDatabase;
+import android.hardware.Camera;
+import android.hardware.Camera.PreviewCallback;
 import android.media.MediaPlayer;
 import android.media.MediaRecorder;
+import android.os.Looper;
 import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
@@ -42,6 +45,8 @@
 import android.media.MediaMetadataRetriever;
 import com.android.mediaframeworktest.MediaProfileReader;
 
+import android.hardware.Camera.PreviewCallback;
+
 /**
  * Junit / Instrumentation - performance measurement for media player and 
  * recorder
@@ -58,14 +63,24 @@
     private static final String MEDIA_MEMORY_OUTPUT =
         "/sdcard/mediaMemOutput.txt";
 
-    //the tolerant memory leak
-    private static final int MAX_ACCEPTED_MEMORY_LEAK_KB = 150;
-
     private static int mStartMemory = 0;
     private static int mEndMemory = 0;
     private static int mStartPid = 0;
     private static int mEndPid = 0;
 
+    private boolean mInitialized = false;
+    private Looper mLooper = null;
+    private RawPreviewCallback mRawPreviewCallback = new RawPreviewCallback();
+    private final Object lock = new Object();
+    private final Object previewDone = new Object();
+    private static int WAIT_FOR_COMMAND_TO_COMPLETE = 10000;  // Milliseconds.
+
+    //the tolerant memory leak
+    private static int ENCODER_LIMIT = 150;
+    private static int DECODER_LIMIT = 150;
+    private static int CAMERA_LIMIT = 80;
+
+    Camera mCamera;
 
     public MediaPlayerPerformance() {
         super("com.android.mediaframeworktest", MediaFrameworkTest.class);
@@ -178,6 +193,66 @@
         Log.v(TAG, "Average duration = " + sum / testFile.length);
     }
 
+    private void initializeMessageLooper() {
+        new Thread() {
+            @Override
+            public void run() {
+                Looper.prepare();
+                Log.v(TAG, "start loopRun");
+                mLooper = Looper.myLooper();
+                mCamera = Camera.open();
+                synchronized (lock) {
+                    mInitialized = true;
+                    lock.notify();
+                }
+                Looper.loop();
+                Log.v(TAG, "initializeMessageLooper: quit.");
+            }
+        }.start();
+    }
+
+    private void terminateMessageLooper() {
+        mLooper.quit();
+        mCamera.release();
+    }
+
+    private final class RawPreviewCallback implements PreviewCallback {
+        public void onPreviewFrame(byte[] rawData, Camera camera) {
+            synchronized (previewDone) {
+                previewDone.notify();
+            }
+        }
+    }
+
+    public void stressCameraPreview() {
+        try {
+            synchronized (lock) {
+                initializeMessageLooper();
+                try {
+                    lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+                } catch (Exception e) {
+                    Log.v(TAG, "runTestOnMethod: wait was interrupted.");
+                }
+            }
+            mCamera.setPreviewCallback(mRawPreviewCallback);
+            mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+            mCamera.setPreviewDisplay(mSurfaceHolder);
+            mCamera.startPreview();
+            synchronized (previewDone) {
+                try {
+                    previewDone.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+                    Log.v(TAG, "Preview Done");
+                } catch (Exception e) {
+                    Log.v(TAG, "wait was interrupted.");
+                }
+            }
+            Thread.sleep(1000);
+            mCamera.stopPreview();
+            terminateMessageLooper();
+        } catch (Exception e) {
+            Log.v(TAG, e.toString());
+        }
+    }
 
     // Note: This test is to assume the mediaserver's pid is 34
     public void mediaStressPlayback(String testFilePath) {
@@ -314,8 +389,9 @@
         return vsizevalue;
     }
 
-    public boolean validateMemoryResult (int startPid, int startMemory, Writer output) throws Exception {
-        //Wait for 10 seconds to make sure the memory settle.
+    public boolean validateMemoryResult(int startPid, int startMemory, Writer output, int limit)
+            throws Exception {
+        // Wait for 10 seconds to make sure the memory settle.
         Thread.sleep(10000);
         mEndPid = getMediaserverPid();
         int memDiff = mEndMemory - startMemory;
@@ -329,9 +405,8 @@
             output.write("mediaserver died. Test failed\n");
             return false;
         }
-        //memory leak greter than the tolerant
-        if (memDiff > MAX_ACCEPTED_MEMORY_LEAK_KB )
-            return false;
+        // memory leak greter than the tolerant
+        if (memDiff > limit) return false;
         return true;
     }
 
@@ -356,7 +431,7 @@
             getMemoryWriteToLog(output, i);
         }
         output.write("\n");
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output);
+        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, DECODER_LIMIT);
         output.close();
         assertTrue("H263 playback memory test", memoryResult);
     }
@@ -375,7 +450,7 @@
             getMemoryWriteToLog(output, i);
         }
         output.write("\n");
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output);
+        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, DECODER_LIMIT);
         output.close();
         assertTrue("H264 playback memory test", memoryResult);
     }
@@ -394,7 +469,7 @@
                 getMemoryWriteToLog(output, i);
             }
             output.write("\n");
-            memoryResult = validateMemoryResult(mStartPid, mStartMemory, output);
+            memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, DECODER_LIMIT);
             output.close();
             assertTrue("wmv playback memory test", memoryResult);
         }
@@ -415,7 +490,7 @@
             getMemoryWriteToLog(output, i);
         }
         output.write("\n");
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output);
+        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, ENCODER_LIMIT);
         output.close();
         assertTrue("H263 record only memory test", memoryResult);
     }
@@ -435,7 +510,7 @@
             getMemoryWriteToLog(output, i);
         }
         output.write("\n");
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output);
+        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, ENCODER_LIMIT);
         output.close();
         assertTrue("mpeg4 record only memory test", memoryResult);
     }
@@ -456,7 +531,7 @@
             getMemoryWriteToLog(output, i);
         }
         output.write("\n");
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output);
+        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, ENCODER_LIMIT);
         output.close();
         assertTrue("H263 audio video record memory test", memoryResult);
     }
@@ -475,8 +550,27 @@
             getMemoryWriteToLog(output, i);
         }
         output.write("\n");
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output);
+        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, ENCODER_LIMIT);
         output.close();
         assertTrue("audio record only memory test", memoryResult);
     }
+
+    // Test case 8: Capture the memory usage after every 20 camera preview
+    @LargeTest
+    public void testCameraPreviewMemoryUsage() throws Exception {
+        boolean memoryResult = false;
+        mStartPid = getMediaserverPid();
+
+        File cameraPreviewMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
+        Writer output = new BufferedWriter(new FileWriter(cameraPreviewMemoryOut, true));
+        output.write("Camera Preview Only\n");
+        for (int i = 0; i < NUM_STRESS_LOOP; i++) {
+            stressCameraPreview();
+            getMemoryWriteToLog(output, i);
+        }
+        output.write("\n");
+        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output, CAMERA_LIMIT);
+        output.close();
+        assertTrue("camera preview memory test", memoryResult);
+    }
 }
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index 25ebee4..547a2a1 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -421,9 +421,19 @@
                     }
                     break;
                 case MSG_ENABLE_LOCATION_UPDATES:
-                    if (mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
+                    boolean networkLocationEnabled;
+                    try {
+                        networkLocationEnabled =
+                            mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
+                    } catch (Exception e) {
+                        // we may get IllegalArgumentException if network location provider
+                        // does not exist or is not yet installed.
+                        networkLocationEnabled = false;
+                    }
+                    if (networkLocationEnabled) {
                         mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
-                                LOCATION_UPDATE_MS, LOCATION_UPDATE_DISTANCE_METER, mLocationListener);
+                                LOCATION_UPDATE_MS, LOCATION_UPDATE_DISTANCE_METER, 
+                                mLocationListener);
                         retrieveLocation();
                         if (mCarModeEnabled && mLocation != null && mNightMode == MODE_NIGHT_AUTO) {
                             try {
diff --git a/services/java/com/android/server/InputDevice.java b/services/java/com/android/server/InputDevice.java
index 1c18d6f..d5e94ec 100644
--- a/services/java/com/android/server/InputDevice.java
+++ b/services/java/com/android/server/InputDevice.java
@@ -22,6 +22,8 @@
 import android.view.Surface;
 import android.view.WindowManagerPolicy;
 
+import java.io.PrintWriter;
+
 public class InputDevice {
     static final boolean DEBUG_POINTERS = false;
     static final boolean DEBUG_HACKS = false;
@@ -58,6 +60,7 @@
         float yMoveScale;
         MotionEvent currentMove = null;
         boolean changed = false;
+        boolean everChanged = false;
         long mDownTime = 0;
         
         // The currently assigned pointer IDs, corresponding to the last data.
@@ -103,6 +106,56 @@
         int mAddingPointerOffset = 0;
         final boolean[] mDown = new boolean[MAX_POINTERS];
         
+        void dumpIntArray(PrintWriter pw, int[] array) {
+            pw.print("[");
+            for (int i=0; i<array.length; i++) {
+                if (i > 0) pw.print(", ");
+                pw.print(array[i]);
+            }
+            pw.print("]");
+        }
+        
+        void dumpBooleanArray(PrintWriter pw, boolean[] array) {
+            pw.print("[");
+            for (int i=0; i<array.length; i++) {
+                if (i > 0) pw.print(", ");
+                pw.print(array[i] ? "true" : "false");
+            }
+            pw.print("]");
+        }
+        
+        void dump(PrintWriter pw, String prefix) {
+            pw.print(prefix); pw.print("xPrecision="); pw.print(xPrecision);
+                    pw.print(" yPrecision="); pw.println(yPrecision);
+            pw.print(prefix); pw.print("xMoveScale="); pw.print(xMoveScale);
+                    pw.print(" yMoveScale="); pw.println(yMoveScale);
+            if (currentMove != null) {
+                pw.print(prefix); pw.print("currentMove="); pw.println(currentMove);
+            }
+            if (changed || mDownTime != 0) {
+                pw.print(prefix); pw.print("changed="); pw.print(changed);
+                        pw.print(" mDownTime="); pw.println(mDownTime);
+            }
+            pw.print(prefix); pw.print("mPointerIds="); dumpIntArray(pw, mPointerIds);
+                    pw.println("");
+            if (mSkipLastPointers || mLastNumPointers != 0) {
+                pw.print(prefix); pw.print("mSkipLastPointers="); pw.print(mSkipLastPointers);
+                        pw.print(" mLastNumPointers="); pw.println(mLastNumPointers);
+                pw.print(prefix); pw.print("mLastData="); dumpIntArray(pw, mLastData);
+                        pw.println("");
+            }
+            if (mNextNumPointers != 0) {
+                pw.print(prefix); pw.print("mNextNumPointers="); pw.println(mNextNumPointers);
+                pw.print(prefix); pw.print("mNextData="); dumpIntArray(pw, mNextData);
+                        pw.println("");
+            }
+            pw.print(prefix); pw.print("mDroppedBadPoint=");
+                    dumpBooleanArray(pw, mDroppedBadPoint); pw.println("");
+            pw.print(prefix); pw.print("mAddingPointerOffset="); pw.println(mAddingPointerOffset);
+            pw.print(prefix); pw.print("mDown=");
+                    dumpBooleanArray(pw, mDown); pw.println("");
+        }
+        
         MotionState(int mx, int my) {
             xPrecision = mx;
             yPrecision = my;
@@ -775,6 +828,14 @@
         int range;
         int flat;
         int fuzz;
+        
+        final void dump(PrintWriter pw) {
+            pw.print("minValue="); pw.print(minValue);
+            pw.print(" maxValue="); pw.print(maxValue);
+            pw.print(" range="); pw.print(range);
+            pw.print(" flat="); pw.print(flat);
+            pw.print(" fuzz="); pw.print(fuzz);
+        }
     };
     
     InputDevice(int _id, int _classes, String _name,
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index a6a3e27..60813f1 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -1475,13 +1475,22 @@
 
         final List<InputMethodInfo> immis = getEnabledInputMethodList();
 
-        int N = (immis == null ? 0 : immis.size());
+        if (immis == null) {
+            return;
+        }
+        
+        int N = immis.size();
 
         mItems = new CharSequence[N];
         mIms = new InputMethodInfo[N];
 
         for (int i = 0; i < N; ++i) {
             InputMethodInfo property = immis.get(i);
+            if (property == null) {
+                i--;
+                N--;
+                continue;
+            }
             mItems[i] = property.loadLabel(pm);
             mIms[i] = property;
         }
@@ -1517,6 +1526,9 @@
         mDialogBuilder.setSingleChoiceItems(mItems, checkedItem,
                 new AlertDialog.OnClickListener() {
                     public void onClick(DialogInterface dialog, int which) {
+                        if (mIms == null) {
+                            return;
+                        }
                         synchronized (mMethodMap) {
                             InputMethodInfo im = mIms[which];
                             hideInputMethodMenu();
diff --git a/services/java/com/android/server/KeyInputQueue.java b/services/java/com/android/server/KeyInputQueue.java
index 0535d4c..a08258a 100644
--- a/services/java/com/android/server/KeyInputQueue.java
+++ b/services/java/com/android/server/KeyInputQueue.java
@@ -22,6 +22,7 @@
 import android.os.LatencyTimer;
 import android.os.PowerManager;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.Xml;
@@ -43,6 +44,7 @@
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 
 public abstract class KeyInputQueue {
@@ -738,6 +740,7 @@
                                 
                                 InputDevice.MotionState ms = di.mAbs;
                                 if (ms.changed) {
+                                    ms.everChanged = true;
                                     ms.changed = false;
                                     
                                     if ((classes&(RawInputEvent.CLASS_TOUCHSCREEN
@@ -809,6 +812,7 @@
                                 
                                 ms = di.mRel;
                                 if (ms.changed) {
+                                    ms.everChanged = true;
                                     ms.changed = false;
                                     
                                     me = ms.generateRelMotion(di, curTime,
@@ -1280,4 +1284,91 @@
         return null;
     }
     private static native boolean readEvent(RawInputEvent outEvent);
+    
+    void dump(PrintWriter pw, String prefix) {
+        synchronized (mFirst) {
+            for (int i=0; i<mDevices.size(); i++) {
+                InputDevice dev = mDevices.valueAt(i);
+                pw.print(prefix); pw.print("Device #");
+                        pw.print(mDevices.keyAt(i)); pw.print(" ");
+                        pw.print(dev.name); pw.print(" (classes=0x");
+                        pw.print(Integer.toHexString(dev.classes));
+                        pw.println("):");
+                pw.print(prefix); pw.print("  mKeyDownTime=");
+                        pw.print(dev.mKeyDownTime); pw.print(" mMetaKeysState=");
+                        pw.println(dev.mMetaKeysState);
+                if (dev.absX != null) {
+                    pw.print(prefix); pw.print("  absX: "); dev.absX.dump(pw);
+                            pw.println("");
+                }
+                if (dev.absY != null) {
+                    pw.print(prefix); pw.print("  absY: "); dev.absY.dump(pw);
+                            pw.println("");
+                }
+                if (dev.absPressure != null) {
+                    pw.print(prefix); pw.print("  absPressure: ");
+                            dev.absPressure.dump(pw); pw.println("");
+                }
+                if (dev.absSize != null) {
+                    pw.print(prefix); pw.print("  absSize: ");
+                            dev.absSize.dump(pw); pw.println("");
+                }
+                if (dev.mAbs.everChanged) {
+                    pw.print(prefix); pw.println("  mAbs:");
+                    dev.mAbs.dump(pw, prefix + "    ");
+                }
+                if (dev.mRel.everChanged) {
+                    pw.print(prefix); pw.println("  mRel:");
+                    dev.mRel.dump(pw, prefix + "    ");
+                }
+            }
+            pw.println(" ");
+            for (int i=0; i<mIgnoredDevices.size(); i++) {
+                InputDevice dev = mIgnoredDevices.valueAt(i);
+                pw.print(prefix); pw.print("Ignored Device #");
+                        pw.print(mIgnoredDevices.keyAt(i)); pw.print(" ");
+                        pw.print(dev.name); pw.print(" (classes=0x");
+                        pw.print(Integer.toHexString(dev.classes));
+                        pw.println(")");
+            }
+            pw.println(" ");
+            for (int i=0; i<mVirtualKeys.size(); i++) {
+                VirtualKey vk = mVirtualKeys.get(i);
+                pw.print(prefix); pw.print("Virtual Key #");
+                        pw.print(i); pw.println(":");
+                pw.print(prefix); pw.print("  scancode="); pw.println(vk.scancode);
+                pw.print(prefix); pw.print("  centerx="); pw.print(vk.centerx);
+                        pw.print(" centery="); pw.print(vk.centery);
+                        pw.print(" width="); pw.print(vk.width);
+                        pw.print(" height="); pw.println(vk.height);
+                pw.print(prefix); pw.print("  hitLeft="); pw.print(vk.hitLeft);
+                        pw.print(" hitTop="); pw.print(vk.hitTop);
+                        pw.print(" hitRight="); pw.print(vk.hitRight);
+                        pw.print(" hitBottom="); pw.println(vk.hitBottom);
+                if (vk.lastDevice != null) {
+                    pw.print(prefix); pw.print("  lastDevice=#");
+                            pw.println(vk.lastDevice.id);
+                }
+                if (vk.lastKeycode != 0) {
+                    pw.print(prefix); pw.print("  lastKeycode=");
+                            pw.println(vk.lastKeycode);
+                }
+            }
+            pw.println(" ");
+            pw.print(prefix); pw.print("  Default keyboard: ");
+                    pw.println(SystemProperties.get("hw.keyboards.0.devname"));
+            pw.print(prefix); pw.print("  mGlobalMetaState=");
+                    pw.print(mGlobalMetaState); pw.print(" mHaveGlobalMetaState=");
+                    pw.println(mHaveGlobalMetaState);
+            pw.print(prefix); pw.print("  mDisplayWidth=");
+                    pw.print(mDisplayWidth); pw.print(" mDisplayHeight=");
+                    pw.println(mDisplayHeight);
+            pw.print(prefix); pw.print("  mOrientation=");
+                    pw.println(mOrientation);
+            if (mPressedVirtualKey != null) {
+                pw.print(prefix); pw.print("  mPressedVirtualKey.scancode=");
+                        pw.println(mPressedVirtualKey.scancode);
+            }
+        }
+    }
 }
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 67eba3d..8781263 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -10851,6 +10851,10 @@
             return;
         }
 
+        pw.println("Input State:");
+        mQueue.dump(pw, "  ");
+        pw.println(" ");
+        
         synchronized(mWindowMap) {
             pw.println("Current Window Manager state:");
             for (int i=mWindows.size()-1; i>=0; i--) {
@@ -11014,7 +11018,7 @@
             if (mDimAnimator != null) {
                 mDimAnimator.printTo(pw);
             } else {
-                pw.print( "  no DimAnimator ");
+                pw.println( "  no DimAnimator ");
             }
             pw.print("  mInputMethodAnimLayerAdjustment=");
                     pw.print(mInputMethodAnimLayerAdjustment);