Merge "Add security checks for new API"
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java
index bc37244..af2fa9b 100644
--- a/core/java/android/os/Handler.java
+++ b/core/java/android/os/Handler.java
@@ -567,7 +567,7 @@
 
     @Override
     public String toString() {
-        return "Handler{"
+        return "Handler (" + getClass().getName() + ") {"
         + Integer.toHexString(System.identityHashCode(this))
         + "}";
     }
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 0357958..8047f0c 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -748,18 +748,13 @@
 
     /**
      * @param on true set the local Bluetooth module to be connectable
-     *                but not dicoverable
+     *                The dicoverability is recovered to what it was before
+     *                switchConnectable(false) call
      *           false set the local Bluetooth module to be not connectable
      *                 and not dicoverable
      */
     /*package*/ synchronized void switchConnectable(boolean on) {
-        if (on) {
-            // 0 is a dummy value, does not apply for SCAN_MODE_CONNECTABLE
-            setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE, 0, false);
-        } else {
-            // 0 is a dummy value, does not apply for SCAN_MODE_NONE
-            setScanMode(BluetoothAdapter.SCAN_MODE_NONE, 0, false);
-        }
+        setAdapterPropertyBooleanNative("Powered", on ? 1 : 0);
     }
 
     private synchronized boolean setScanMode(int mode, int duration, boolean allowOnlyInOnState) {
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index c114c37..3e5f32e 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -828,7 +828,10 @@
         if (start == measureLimit) {
             TextPaint wp = mWorkPaint;
             wp.set(mPaint);
-            return handleText(wp, 0, 0, 0, 0, runIsRtl, c, x, top, y, bottom, fmi, needWidth);
+            if (fmi != null) {
+                expandMetricsFromPaint(fmi, wp);
+            }
+            return 0f;
         }
 
         // Shaping needs to take into account context up to metric boundaries,
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index ff378a6..6b09049 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1336,8 +1336,10 @@
             sb.append(type);
             sb.append(" fl=#");
             sb.append(Integer.toHexString(flags));
-            sb.append(" fmt=");
-            sb.append(format);
+            if (format != PixelFormat.OPAQUE) {
+                sb.append(" fmt=");
+                sb.append(format);
+            }
             if (windowAnimations != 0) {
                 sb.append(" wanim=0x");
                 sb.append(Integer.toHexString(windowAnimations));
@@ -1373,7 +1375,9 @@
                 sb.append(" sysuil=");
                 sb.append(hasSystemUiListeners);
             }
-            sb.append(" if=0x").append(Integer.toHexString(inputFeatures));
+            if (inputFeatures != 0) {
+                sb.append(" if=0x").append(Integer.toHexString(inputFeatures));
+            }
             sb.append('}');
             return sb.toString();
         }
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 9fbc4a7..f89d490 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -1129,7 +1129,8 @@
      * synchronous call and unable to pump our MessageQueue.
      */
     private void didReceiveAuthenticationChallenge(
-            final int handle, String host, String realm, final boolean useCachedCredentials) {
+            final int handle, String host, String realm, final boolean useCachedCredentials,
+            final boolean suppressDialog) {
 
         HttpAuthHandler handler = new HttpAuthHandler() {
 
@@ -1147,6 +1148,11 @@
             public void cancel() {
                 nativeAuthenticationCancel(handle);
             }
+
+            @Override
+            public boolean suppressDialog() {
+                return suppressDialog;
+            }
         };
         mCallbackProxy.onReceivedHttpAuthRequest(handler, host, realm);
     }
diff --git a/core/java/android/webkit/HttpAuthHandler.java b/core/java/android/webkit/HttpAuthHandler.java
index 1797eb4..2fbd1d0 100644
--- a/core/java/android/webkit/HttpAuthHandler.java
+++ b/core/java/android/webkit/HttpAuthHandler.java
@@ -50,4 +50,12 @@
      */
     public void proceed(String username, String password) {
     }
+
+    /**
+     * return true if the prompt dialog should be suppressed.
+     * @hide
+     */
+    public boolean suppressDialog() {
+        return false;
+    }
 }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 04cf69b..cec3fda 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -9657,8 +9657,6 @@
                 com.android.internal.R.layout.text_edit_action_popup_text;
         private TextView mPasteTextView;
         private TextView mReplaceTextView;
-        // Whether or not the Paste action should be available when the action popup is displayed
-        private boolean mWithPaste;
 
         @Override
         protected void createPopupWindow() {
@@ -9694,7 +9692,7 @@
 
         @Override
         public void show() {
-            mPasteTextView.setVisibility(mWithPaste && canPaste() ? View.VISIBLE : View.GONE);
+            mPasteTextView.setVisibility(canPaste() ? View.VISIBLE : View.GONE);
             super.show();
         }
 
@@ -9733,10 +9731,6 @@
 
             return positionY;
         }
-
-        public void setShowWithPaste(boolean withPaste) {
-            mWithPaste = withPaste;
-        }
     }
 
     private abstract class HandleView extends View implements TextViewPositionListener {
@@ -9851,7 +9845,7 @@
             TextView.this.getPositionListener().removeSubscriber(this);
         }
 
-        void showActionPopupWindow(int delay, boolean withPaste) {
+        void showActionPopupWindow(int delay) {
             if (mActionPopupWindow == null) {
                 mActionPopupWindow = new ActionPopupWindow();
             }
@@ -9864,7 +9858,6 @@
             } else {
                 TextView.this.removeCallbacks(mActionPopupShower);
             }
-            mActionPopupWindow.setShowWithPaste(withPaste);
             TextView.this.postDelayed(mActionPopupShower, delay);
         }
 
@@ -9926,6 +9919,7 @@
         }
 
         public void updatePosition(int parentPositionX, int parentPositionY, boolean modified) {
+            positionAtCursorOffset(getCurrentCursorOffset());
             if (modified || mPositionHasChanged) {
                 if (mIsDragging) {
                     // Update touchToWindow offset in case of parent scrolling while dragging
@@ -10049,7 +10043,7 @@
             if (durationSinceCutOrCopy < RECENT_CUT_COPY_DURATION) {
                 delayBeforeShowActionPopup = 0;
             }
-            showActionPopupWindow(delayBeforeShowActionPopup, true);
+            showActionPopupWindow(delayBeforeShowActionPopup);
         }
 
         private void hideAfterDelay() {
@@ -10325,7 +10319,7 @@
 
             // Make sure both left and right handles share the same ActionPopupWindow (so that
             // moving any of the handles hides the action popup).
-            mStartHandle.showActionPopupWindow(DELAY_BEFORE_REPLACE_ACTION, false);
+            mStartHandle.showActionPopupWindow(DELAY_BEFORE_REPLACE_ACTION);
             mEndHandle.setActionPopupWindow(mStartHandle.getActionPopupWindow());
 
             hideInsertionPointCursorController();
@@ -10791,9 +10785,6 @@
     private boolean                 mDPadCenterIsDown = false;
     private boolean                 mEnterKeyIsDown = false;
     private boolean                 mContextMenuTriggeredByKey = false;
-    // Created once and shared by different CursorController helper methods.
-    // Only one cursor controller is active at any time which prevent race conditions.
-    private static Rect             sCursorControllerTempRect = new Rect();
 
     private boolean                 mSelectAllOnFocus = false;
 
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 64749e9..98d7fce 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -325,11 +325,13 @@
         NPE_CHECK_RETURN_ZERO(env, text);
 
         size_t textLength = env->GetArrayLength(text);
-
         if ((index | count) < 0 || (size_t)(index + count) > textLength) {
             doThrowAIOOBE(env);
             return 0;
         }
+        if (count == 0) {
+            return 0;
+        }
 
         SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
         const jchar* textArray = env->GetCharArrayElements(text, NULL);
@@ -350,15 +352,22 @@
         NPE_CHECK_RETURN_ZERO(env, jpaint);
         NPE_CHECK_RETURN_ZERO(env, text);
 
-        SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
-        const jchar* textArray = env->GetStringChars(text, NULL);
-
         int count = end - start;
-        size_t textLength = env->GetStringLength(text);
-        if ((start | count) < 0 || (size_t)count > textLength) {
+        if ((start | count) < 0) {
             doThrowAIOOBE(env);
             return 0;
         }
+        if (count == 0) {
+            return 0;
+        }
+        size_t textLength = env->GetStringLength(text);
+        if ((size_t)count > textLength) {
+            doThrowAIOOBE(env);
+            return 0;
+        }
+
+        const jchar* textArray = env->GetStringChars(text, NULL);
+        SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
         jfloat width = 0;
 
 #if RTL_USE_HARFBUZZ
@@ -376,10 +385,15 @@
         NPE_CHECK_RETURN_ZERO(env, jpaint);
         NPE_CHECK_RETURN_ZERO(env, text);
 
-        SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
-        const jchar* textArray = env->GetStringChars(text, NULL);
         size_t textLength = env->GetStringLength(text);
+        if (textLength == 0) {
+            return 0;
+        }
+
+        const jchar* textArray = env->GetStringChars(text, NULL);
+        SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
         jfloat width = 0;
+
 #if RTL_USE_HARFBUZZ
         TextLayout::getTextRunAdvances(paint, textArray, 0, textLength, textLength,
                 paint->getFlags(), NULL /* dont need all advances */, width);
@@ -391,8 +405,25 @@
     }
 
     static int dotextwidths(JNIEnv* env, SkPaint* paint, const jchar text[], int count, jfloatArray widths) {
+        NPE_CHECK_RETURN_ZERO(env, paint);
+        NPE_CHECK_RETURN_ZERO(env, text);
+
+        if (count < 0 || !widths) {
+            doThrowAIOOBE(env);
+            return 0;
+        }
+        if (count == 0) {
+            return 0;
+        }
+        size_t widthsLength = env->GetArrayLength(widths);
+        if ((size_t)count > widthsLength) {
+            doThrowAIOOBE(env);
+            return 0;
+        }
+
         AutoJavaFloatArray autoWidths(env, widths, count);
         jfloat* widthsArray = autoWidths.ptr();
+
 #if RTL_USE_HARFBUZZ
         jfloat totalAdvance;
 
@@ -427,6 +458,22 @@
 
     static int doTextGlyphs(JNIEnv* env, SkPaint* paint, const jchar* text, jint start, jint count,
             jint contextCount, jint flags, jcharArray glyphs) {
+        NPE_CHECK_RETURN_ZERO(env, paint);
+        NPE_CHECK_RETURN_ZERO(env, text);
+
+        if ((start | count | contextCount) < 0 || contextCount < count || !glyphs) {
+            doThrowAIOOBE(env);
+            return 0;
+        }
+        if (count == 0) {
+            return 0;
+        }
+        size_t glypthsLength = env->GetArrayLength(glyphs);
+        if ((size_t)count > glypthsLength) {
+            doThrowAIOOBE(env);
+            return 0;
+        }
+
         jchar* glyphsArray = env->GetCharArrayElements(glyphs, NULL);
         HB_ShaperItem shaperItem;
         HB_FontRec font;
@@ -455,8 +502,25 @@
     static jfloat doTextRunAdvances(JNIEnv *env, SkPaint *paint, const jchar *text,
                                     jint start, jint count, jint contextCount, jint flags,
                                     jfloatArray advances, jint advancesIndex) {
+        NPE_CHECK_RETURN_ZERO(env, paint);
+        NPE_CHECK_RETURN_ZERO(env, text);
+
+        if ((start | count | contextCount | advancesIndex) < 0 || contextCount < count) {
+            doThrowAIOOBE(env);
+            return 0;
+        }
+        if (count == 0) {
+            return 0;
+        }
+        if (advances) {
+            size_t advancesLength = env->GetArrayLength(advances);
+            if ((size_t)count > advancesLength) {
+                doThrowAIOOBE(env);
+                return 0;
+            }
+        }
         jfloat advancesArray[count];
-        jfloat totalAdvance;
+        jfloat totalAdvance = 0;
 
         TextLayout::getTextRunAdvances(paint, text, start, count, contextCount, flags,
                                        advancesArray, totalAdvance);
@@ -470,8 +534,26 @@
     static jfloat doTextRunAdvancesICU(JNIEnv *env, SkPaint *paint, const jchar *text,
                                     jint start, jint count, jint contextCount, jint flags,
                                     jfloatArray advances, jint advancesIndex) {
+        NPE_CHECK_RETURN_ZERO(env, paint);
+        NPE_CHECK_RETURN_ZERO(env, text);
+
+        if ((start | count | contextCount | advancesIndex) < 0 || contextCount < count) {
+            doThrowAIOOBE(env);
+            return 0;
+        }
+        if (count == 0) {
+            return 0;
+        }
+        if (advances) {
+            size_t advancesLength = env->GetArrayLength(advances);
+            if ((size_t)count > advancesLength) {
+                doThrowAIOOBE(env);
+                return 0;
+            }
+        }
+
         jfloat advancesArray[count];
-        jfloat totalAdvance;
+        jfloat totalAdvance = 0;
 
         TextLayout::getTextRunAdvancesICU(paint, text, start, count, contextCount, flags,
                                        advancesArray, totalAdvance);
@@ -512,7 +594,7 @@
             jint count, jint flags, jint offset, jint opt) {
 #if RTL_USE_HARFBUZZ
         jfloat scalarArray[count];
-        jfloat totalAdvance;
+        jfloat totalAdvance = 0;
 
         TextLayout::getTextRunAdvances(paint, text, start, count, count, flags,
                 scalarArray, totalAdvance);
diff --git a/core/res/res/layout/keyguard_screen_password_landscape.xml b/core/res/res/layout/keyguard_screen_password_landscape.xml
index 452b982..4c44049 100644
--- a/core/res/res/layout/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_password_landscape.xml
@@ -66,13 +66,15 @@
 
     <TextView
         android:id="@+id/date"
+        android:layout_width="0dip"
+        android:layout_gravity="fill_horizontal"
+        android:gravity="right"
         android:layout_below="@id/time"
         android:layout_marginTop="6dip"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
-        android:layout_gravity="right"
         />
 
     <TextView
@@ -88,22 +90,26 @@
 
     <TextView
         android:id="@+id/status1"
+        android:layout_width="0dip"
+        android:layout_gravity="fill_horizontal"
+        android:gravity="right"
         android:layout_marginTop="4dip"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:drawablePadding="4dip"
-        android:layout_gravity="right"
         />
 
     <Space android:layout_gravity="fill" />
 
     <TextView
         android:id="@+id/carrier"
+        android:layout_width="0dip"
+        android:layout_gravity="fill_horizontal"
+        android:gravity="right"
         android:singleLine="true"
         android:ellipsize="marquee"
-        android:layout_gravity="right"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:textColor="?android:attr/textColorSecondary"
@@ -144,6 +150,7 @@
             android:background="@drawable/lockscreen_password_field_dark"
             android:textColor="?android:attr/textColorPrimary"
             android:imeOptions="flagNoFullscreen|actionDone"
+            android:suggestionsEnabled="false"
             />
 
     </LinearLayout>
diff --git a/core/res/res/layout/keyguard_screen_password_portrait.xml b/core/res/res/layout/keyguard_screen_password_portrait.xml
index cd33275..1d0ea54 100644
--- a/core/res/res/layout/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_password_portrait.xml
@@ -109,7 +109,8 @@
         android:background="@drawable/lockscreen_password_field_dark"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textColor="#ffffffff"
-        android:imeOptions="actionDone"/>
+        android:imeOptions="actionDone"
+        android:suggestionsEnabled="false"/>
 
     <!-- Numeric keyboard -->
     <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
index 168bd1a..0568dd9 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -64,13 +64,14 @@
 
     <TextView
         android:id="@+id/date"
-        android:layout_below="@id/time"
+        android:layout_width="0dip"
+        android:layout_gravity="fill_horizontal"
+        android:gravity="right"
         android:layout_marginTop="6dip"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
-        android:layout_gravity="right"
         />
 
     <TextView
@@ -86,22 +87,24 @@
 
     <TextView
         android:id="@+id/status1"
+        android:layout_width="0dip"
+        android:layout_gravity="fill_horizontal"
+        android:gravity="right"
         android:layout_marginTop="4dip"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
         android:drawablePadding="4dip"
-        android:layout_gravity="right"
         />
 
     <Space android:layout_gravity="fill" />
 
     <TextView
         android:id="@+id/carrier"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="right"
+        android:layout_width="0dip"
+        android:layout_gravity="fill_horizontal"
+        android:gravity="right"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
diff --git a/core/res/res/layout/keyguard_screen_unlock_landscape.xml b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
index c425b73..9b28731 100644
--- a/core/res/res/layout/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
@@ -64,11 +64,13 @@
 
     <TextView
         android:id="@+id/date"
+        android:layout_width="0dip"
+        android:layout_gravity="fill_horizontal"
+        android:gravity="right"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
-        android:layout_gravity="right"
         />
 
     <TextView
@@ -83,17 +85,21 @@
 
     <TextView
         android:id="@+id/status1"
+        android:layout_width="0dip"
+        android:layout_gravity="fill_horizontal"
+        android:gravity="right"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
-        android:layout_gravity="right"
         />
 
     <Space android:layout_gravity="fill" />
 
     <TextView android:id="@+id/carrier"
-        android:layout_gravity="right"
+        android:layout_width="0dip"
+        android:layout_gravity="fill_horizontal"
+        android:gravity="right"
         android:singleLine="true"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 1df8143..e509ee0 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1185,6 +1185,9 @@
      * @return      The width of the text
      */
     public float measureText(char[] text, int index, int count) {
+        if (text == null || text.length == 0 || count == 0) {
+            return 0f;
+        }
         if (!mHasCompatScaling) return native_measureText(text, index, count);
         final float oldSize = getTextSize();
         setTextSize(oldSize*mCompatScaling);
@@ -1204,6 +1207,9 @@
      * @return      The width of the text
      */
     public float measureText(String text, int start, int end) {
+        if (text == null || text.length() == 0 || start == end) {
+            return 0f;
+        }
         if (!mHasCompatScaling) return native_measureText(text, start, end);
         final float oldSize = getTextSize();
         setTextSize(oldSize*mCompatScaling);
@@ -1221,6 +1227,9 @@
      * @return      The width of the text
      */
     public float measureText(String text) {
+        if (text == null || text.length() == 0) {
+            return 0f;
+        }
         if (!mHasCompatScaling) return native_measureText(text);
         final float oldSize = getTextSize();
         setTextSize(oldSize*mCompatScaling);
@@ -1240,6 +1249,9 @@
      * @return      The width of the text
      */
     public float measureText(CharSequence text, int start, int end) {
+        if (text == null || text.length() == 0 || start == end) {
+            return 0f;
+        }
         if (text instanceof String) {
             return measureText((String)text, start, end);
         }
@@ -1275,6 +1287,9 @@
      */
     public int breakText(char[] text, int index, int count,
                                 float maxWidth, float[] measuredWidth) {
+        if (text == null || text.length == 0 || count == 0) {
+            return 0;
+        }
         if (!mHasCompatScaling) {
             return native_breakText(text, index, count, maxWidth, measuredWidth);
         }
@@ -1309,6 +1324,9 @@
     public int breakText(CharSequence text, int start, int end,
                          boolean measureForwards,
                          float maxWidth, float[] measuredWidth) {
+        if (text == null || text.length() == 0 || start == end) {
+            return 0;
+        }
         if (start == 0 && text instanceof String && end == text.length()) {
             return breakText((String) text, measureForwards, maxWidth,
                              measuredWidth);
@@ -1347,6 +1365,9 @@
      */
     public int breakText(String text, boolean measureForwards,
                                 float maxWidth, float[] measuredWidth) {
+        if (text == null || text.length() == 0) {
+            return 0;
+        }
         if (!mHasCompatScaling) {
             return native_breakText(text, measureForwards, maxWidth, measuredWidth);
         }
@@ -1374,6 +1395,9 @@
      */
     public int getTextWidths(char[] text, int index, int count,
                              float[] widths) {
+        if (text == null || text.length == 0 || count == 0) {
+            return 0;
+        }
         if ((index | count) < 0 || index + count > text.length
                 || count > widths.length) {
             throw new ArrayIndexOutOfBoundsException();
@@ -1404,6 +1428,9 @@
      */
     public int getTextWidths(CharSequence text, int start, int end,
                              float[] widths) {
+        if (text == null || text.length() == 0 || start == end) {
+            return 0;
+        }
         if (text instanceof String) {
             return getTextWidths((String) text, start, end, widths);
         }
@@ -1434,6 +1461,9 @@
      * @return       the number of unichars in the specified text.
      */
     public int getTextWidths(String text, int start, int end, float[] widths) {
+        if (text == null || text.length() == 0 || start == end) {
+            return 0;
+        }
         if ((start | end | (end - start) | (text.length() - end)) < 0) {
             throw new IndexOutOfBoundsException();
         }
@@ -1528,6 +1558,9 @@
             int contextIndex, int contextCount, int flags, float[] advances,
             int advancesIndex, int reserved) {
 
+        if (chars == null || chars.length == 0){
+            return 0f;
+        }
         if ((index | count | contextIndex | contextCount | advancesIndex
                 | (index - contextIndex)
                 | ((contextIndex + contextCount) - (index + count))
@@ -1584,6 +1617,9 @@
             int contextStart, int contextEnd, int flags, float[] advances,
             int advancesIndex, int reserved) {
 
+        if (text == null || text.length() == 0) {
+            return 0f;
+        }
         if (text instanceof String) {
             return getTextRunAdvances((String) text, start, end,
                     contextStart, contextEnd, flags, advances, advancesIndex, reserved);
@@ -1702,6 +1738,9 @@
     public float getTextRunAdvances(String text, int start, int end, int contextStart,
             int contextEnd, int flags, float[] advances, int advancesIndex, int reserved) {
 
+        if (text == null || text.length() == 0 || start == end || contextStart == contextEnd) {
+            return 0f;
+        }
         if ((start | end | contextStart | contextEnd | advancesIndex | (end - start)
                 | (start - contextStart) | (contextEnd - end)
                 | (text.length() - contextEnd)
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index f20e234..eb22e32 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -108,6 +108,8 @@
     static unsigned int  getInputFramesLost(audio_io_handle_t ioHandle);
 
     static int newAudioSessionId();
+    static void acquireAudioSessionId(int audioSession);
+    static void releaseAudioSessionId(int audioSession);
 
     // types of io configuration change events received with ioConfigChanged()
     enum io_config_event {
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index 4037c46..9e3cb7f 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -139,6 +139,9 @@
 
     virtual int newAudioSessionId() = 0;
 
+    virtual void acquireAudioSessionId(int audioSession) = 0;
+    virtual void releaseAudioSessionId(int audioSession) = 0;
+
     virtual status_t queryNumberEffects(uint32_t *numEffects) = 0;
 
     virtual status_t queryEffect(uint32_t index, effect_descriptor_t *pDescriptor) = 0;
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 16554c2..e5062ab 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -114,6 +114,7 @@
         }
         mAudioRecord.clear();
         IPCThreadState::self()->flushCommands();
+        AudioSystem::releaseAudioSessionId(mSessionId);
     }
 }
 
@@ -233,6 +234,7 @@
     mInputSource = (uint8_t)inputSource;
     mFlags = flags;
     mInput = input;
+    AudioSystem::acquireAudioSessionId(mSessionId);
 
     return NO_ERROR;
 }
@@ -465,6 +467,7 @@
                                                        ((uint16_t)flags) << 16,
                                                        &mSessionId,
                                                        &status);
+
     if (record == 0) {
         LOGE("AudioFlinger could not create record track, status: %d", status);
         return status;
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 5009957..b26ed71 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -356,6 +356,20 @@
     return af->newAudioSessionId();
 }
 
+void AudioSystem::acquireAudioSessionId(int audioSession) {
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af != 0) {
+        af->acquireAudioSessionId(audioSession);
+    }
+}
+
+void AudioSystem::releaseAudioSessionId(int audioSession) {
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af != 0) {
+        af->releaseAudioSessionId(audioSession);
+    }
+}
+
 // ---------------------------------------------------------------------------
 
 void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) {
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 31eb97a..3949c39 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -134,6 +134,7 @@
         }
         mAudioTrack.clear();
         IPCThreadState::self()->flushCommands();
+        AudioSystem::releaseAudioSessionId(mSessionId);
     }
 }
 
@@ -259,6 +260,7 @@
     mNewPosition = 0;
     mUpdatePeriod = 0;
     mFlags = flags;
+    AudioSystem::acquireAudioSessionId(mSessionId);
 
     return NO_ERROR;
 }
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 4a12962..d58834b 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -1,4 +1,4 @@
-/* //device/extlibs/pv/android/IAudioflinger.cpp
+/*
 **
 ** Copyright 2007, The Android Open Source Project
 **
@@ -63,6 +63,8 @@
     GET_RENDER_POSITION,
     GET_INPUT_FRAMES_LOST,
     NEW_AUDIO_SESSION_ID,
+    ACQUIRE_AUDIO_SESSION_ID,
+    RELEASE_AUDIO_SESSION_ID,
     QUERY_NUM_EFFECTS,
     QUERY_EFFECT,
     GET_EFFECT_DESCRIPTOR,
@@ -526,6 +528,22 @@
         return id;
     }
 
+    virtual void acquireAudioSessionId(int audioSession)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(audioSession);
+        remote()->transact(ACQUIRE_AUDIO_SESSION_ID, data, &reply);
+    }
+
+    virtual void releaseAudioSessionId(int audioSession)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(audioSession);
+        remote()->transact(RELEASE_AUDIO_SESSION_ID, data, &reply);
+    }
+
     virtual status_t queryNumberEffects(uint32_t *numEffects)
     {
         Parcel data, reply;
@@ -919,6 +937,18 @@
             reply->writeInt32(newAudioSessionId());
             return NO_ERROR;
         } break;
+        case ACQUIRE_AUDIO_SESSION_ID: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            int audioSession = data.readInt32();
+            acquireAudioSessionId(audioSession);
+            return NO_ERROR;
+        } break;
+        case RELEASE_AUDIO_SESSION_ID: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            int audioSession = data.readInt32();
+            releaseAudioSessionId(audioSession);
+            return NO_ERROR;
+        } break;
         case QUERY_NUM_EFFECTS: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             uint32_t numEffects;
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 3dd9249..67a66a2 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -61,12 +61,14 @@
     mVideoWidth = mVideoHeight = 0;
     mLockThreadId = 0;
     mAudioSessionId = AudioSystem::newAudioSessionId();
+    AudioSystem::acquireAudioSessionId(mAudioSessionId);
     mSendLevel = 0;
 }
 
 MediaPlayer::~MediaPlayer()
 {
     LOGV("destructor");
+    AudioSystem::releaseAudioSessionId(mAudioSessionId);
     disconnect();
     IPCThreadState::self()->flushCommands();
 }
@@ -618,7 +620,11 @@
     if (sessionId < 0) {
         return BAD_VALUE;
     }
-    mAudioSessionId = sessionId;
+    if (sessionId != mAudioSessionId) {
+      AudioSystem::releaseAudioSessionId(mAudioSessionId);
+      AudioSystem::acquireAudioSessionId(sessionId);
+      mAudioSessionId = sessionId;
+    }
     return NO_ERROR;
 }
 
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index ea8eaa4..ac3565f 100755
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -665,7 +665,7 @@
     LOGV("releaseRecordingFrame");
     if (mCameraRecordingProxy != NULL) {
         mCameraRecordingProxy->releaseRecordingFrame(frame);
-    } else {
+    } else if (mCamera != NULL) {
         int64_t token = IPCThreadState::self()->clearCallingIdentity();
         mCamera->releaseRecordingFrame(frame);
         IPCThreadState::self()->restoreCallingIdentity(token);
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index e201b17..d6bfda6 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -264,6 +264,14 @@
             }
         }
     }
+
+    result.append("Global session refs:\n");
+    result.append(" session pid cnt\n");
+    for (size_t i = 0; i < mAudioSessionRefs.size(); i++) {
+        AudioSessionRef *r = mAudioSessionRefs[i];
+        snprintf(buffer, SIZE, " %7d %3d %3d\n", r->sessionid, r->pid, r->cnt);
+        result.append(buffer);
+    }
     write(fd, result.string(), result.size());
     return NO_ERROR;
 }
@@ -892,6 +900,25 @@
         LOGV("removeNotificationClient() %p, pid %d", client.get(), pid);
         mNotificationClients.removeItem(pid);
     }
+
+    LOGV("%d died, releasing its sessions", pid);
+    int num = mAudioSessionRefs.size();
+    bool removed = false;
+    for (int i = 0; i< num; i++) {
+        AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
+        LOGV(" pid %d @ %d", ref->pid, i);
+        if (ref->pid == pid) {
+            LOGV(" removing entry for pid %d session %d", pid, ref->sessionid);
+            mAudioSessionRefs.removeAt(i);
+            delete ref;
+            removed = true;
+            i--;
+            num--;
+        }
+    }
+    if (removed) {
+        purgeStaleEffects_l();
+    }
 }
 
 // audioConfigChanged_l() must be called with AudioFlinger::mLock held
@@ -5042,6 +5069,109 @@
     return nextUniqueId();
 }
 
+void AudioFlinger::acquireAudioSessionId(int audioSession)
+{
+    Mutex::Autolock _l(mLock);
+    int caller = IPCThreadState::self()->getCallingPid();
+    LOGV("acquiring %d from %d", audioSession, caller);
+    int num = mAudioSessionRefs.size();
+    for (int i = 0; i< num; i++) {
+        AudioSessionRef *ref = mAudioSessionRefs.editItemAt(i);
+        if (ref->sessionid == audioSession && ref->pid == caller) {
+            ref->cnt++;
+            LOGV(" incremented refcount to %d", ref->cnt);
+            return;
+        }
+    }
+    AudioSessionRef *ref = new AudioSessionRef();
+    ref->sessionid = audioSession;
+    ref->pid = caller;
+    ref->cnt = 1;
+    mAudioSessionRefs.push(ref);
+    LOGV(" added new entry for %d", ref->sessionid);
+}
+
+void AudioFlinger::releaseAudioSessionId(int audioSession)
+{
+    Mutex::Autolock _l(mLock);
+    int caller = IPCThreadState::self()->getCallingPid();
+    LOGV("releasing %d from %d", audioSession, caller);
+    int num = mAudioSessionRefs.size();
+    for (int i = 0; i< num; i++) {
+        AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
+        if (ref->sessionid == audioSession && ref->pid == caller) {
+            ref->cnt--;
+            LOGV(" decremented refcount to %d", ref->cnt);
+            if (ref->cnt == 0) {
+                mAudioSessionRefs.removeAt(i);
+                delete ref;
+                purgeStaleEffects_l();
+            }
+            return;
+        }
+    }
+    LOGW("session id %d not found for pid %d", audioSession, caller);
+}
+
+void AudioFlinger::purgeStaleEffects_l() {
+
+    LOGV("purging stale effects");
+
+    Vector< sp<EffectChain> > chains;
+
+    for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+        sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
+        for (size_t j = 0; j < t->mEffectChains.size(); j++) {
+            sp<EffectChain> ec = t->mEffectChains[j];
+            chains.push(ec);
+        }
+    }
+    for (size_t i = 0; i < mRecordThreads.size(); i++) {
+        sp<RecordThread> t = mRecordThreads.valueAt(i);
+        for (size_t j = 0; j < t->mEffectChains.size(); j++) {
+            sp<EffectChain> ec = t->mEffectChains[j];
+            chains.push(ec);
+        }
+    }
+
+    for (size_t i = 0; i < chains.size(); i++) {
+        sp<EffectChain> ec = chains[i];
+        int sessionid = ec->sessionId();
+        sp<ThreadBase> t = ec->mThread.promote();
+        if (t == 0) {
+            continue;
+        }
+        size_t numsessionrefs = mAudioSessionRefs.size();
+        bool found = false;
+        for (size_t k = 0; k < numsessionrefs; k++) {
+            AudioSessionRef *ref = mAudioSessionRefs.itemAt(k);
+            if (ref->sessionid == sessionid) {
+                LOGV(" session %d still exists for %d with %d refs",
+                     sessionid, ref->pid, ref->cnt);
+                found = true;
+                break;
+            }
+        }
+        if (!found) {
+            // remove all effects from the chain
+            while (ec->mEffects.size()) {
+                sp<EffectModule> effect = ec->mEffects[0];
+                effect->unPin();
+                Mutex::Autolock _l (t->mLock);
+                t->removeEffect_l(effect);
+                for (size_t j = 0; j < effect->mHandles.size(); j++) {
+                    sp<EffectHandle> handle = effect->mHandles[j].promote();
+                    if (handle != 0) {
+                        handle->mEffect.clear();
+                    }
+                }
+                AudioSystem::unregisterEffect(effect->id());
+            }
+        }
+    }
+    return;
+}
+
 // checkPlaybackThread_l() must be called with AudioFlinger::mLock held
 AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(int output) const
 {
@@ -5199,6 +5329,7 @@
             }
             uint32_t numEffects = 0;
             effect_descriptor_t d;
+            d.flags = 0; // prevent compiler warning
             bool found = false;
 
             lStatus = EffectQueryNumberEffects(&numEffects);
@@ -5302,7 +5433,7 @@
             mClients.add(pid, client);
         }
 
-        // create effect on selected output trhead
+        // create effect on selected output thread
         handle = thread->createEffect_l(client, effectClient, priority, sessionId,
                 &desc, enabled, &lStatus);
         if (handle != 0 && id != NULL) {
@@ -5344,7 +5475,7 @@
     return NO_ERROR;
 }
 
-// moveEffectChain_l mustbe called with both srcThread and dstThread mLocks held
+// moveEffectChain_l must be called with both srcThread and dstThread mLocks held
 status_t AudioFlinger::moveEffectChain_l(int sessionId,
                                    AudioFlinger::PlaybackThread *srcThread,
                                    AudioFlinger::PlaybackThread *dstThread,
@@ -5370,7 +5501,7 @@
     // correct buffer sizes and audio parameters and effect engines reconfigured accordingly
     int dstOutput = dstThread->id();
     sp<EffectChain> dstChain;
-    uint32_t strategy;
+    uint32_t strategy = 0; // prevent compiler warning
     sp<EffectModule> effect = chain->getEffectFromId_l(0);
     while (effect != 0) {
         srcThread->removeEffect_l(effect);
@@ -5632,14 +5763,17 @@
 }
 
 void AudioFlinger::ThreadBase::disconnectEffect(const sp<EffectModule>& effect,
-                                                    const wp<EffectHandle>& handle) {
+                                                    const wp<EffectHandle>& handle,
+                                                    bool unpiniflast) {
 
     Mutex::Autolock _l(mLock);
     LOGV("disconnectEffect() %p effect %p", this, effect.get());
     // delete the effect module if removing last handle on it
     if (effect->removeHandle(handle) == 0) {
-        removeEffect_l(effect);
-        AudioSystem::unregisterEffect(effect->id());
+        if (!effect->isPinned() || unpiniflast) {
+            removeEffect_l(effect);
+            AudioSystem::unregisterEffect(effect->id());
+        }
     }
 }
 
@@ -5847,6 +5981,9 @@
         goto Error;
     }
 
+    if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
+        mPinned = true;
+    }
     LOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface);
     return;
 Error:
@@ -5938,7 +6075,7 @@
     // Prevent calls to process() and other functions on effect interface from now on.
     // The effect engine will be released by the destructor when the last strong reference on
     // this object is released which can happen after next process is called.
-    if (size == 0) {
+    if (size == 0 && !mPinned) {
         mState = DESTROYED;
     }
 
@@ -5955,9 +6092,7 @@
     return handle;
 }
 
-
-
-void AudioFlinger::EffectModule::disconnect(const wp<EffectHandle>& handle)
+void AudioFlinger::EffectModule::disconnect(const wp<EffectHandle>& handle, bool unpiniflast)
 {
     LOGV("disconnect() %p handle %p ", this, handle.unsafe_get());
     // keep a strong reference on this EffectModule to avoid calling the
@@ -5966,7 +6101,7 @@
     {
         sp<ThreadBase> thread = mThread.promote();
         if (thread != 0) {
-            thread->disconnectEffect(keep, handle);
+            thread->disconnectEffect(keep, handle, unpiniflast);
         }
     }
 }
@@ -6533,11 +6668,14 @@
                                         const sp<IEffectClient>& effectClient,
                                         int32_t priority)
     : BnEffect(),
-    mEffect(effect), mEffectClient(effectClient), mClient(client),
+    mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL),
     mPriority(priority), mHasControl(false), mEnabled(false)
 {
     LOGV("constructor %p", this);
 
+    if (client == 0) {
+        return;
+    }
     int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
     mCblkMemory = client->heap()->allocate(EFFECT_PARAM_BUFFER_SIZE + bufOffset);
     if (mCblkMemory != 0) {
@@ -6556,7 +6694,7 @@
 AudioFlinger::EffectHandle::~EffectHandle()
 {
     LOGV("Destructor %p", this);
-    disconnect();
+    disconnect(false);
     LOGV("Destructor DONE %p", this);
 }
 
@@ -6605,12 +6743,16 @@
 
 void AudioFlinger::EffectHandle::disconnect()
 {
-    LOGV("disconnect %p", this);
+    disconnect(true);
+}
+
+void AudioFlinger::EffectHandle::disconnect(bool unpiniflast)
+{
+    LOGV("disconnect(%s)", unpiniflast ? "true" : "false");
     if (mEffect == 0) {
         return;
     }
-
-    mEffect->disconnect(this);
+    mEffect->disconnect(this, unpiniflast);
 
     sp<ThreadBase> thread = mEffect->thread().promote();
     if (thread != 0) {
@@ -6619,11 +6761,11 @@
 
     // release sp on module => module destructor can be called now
     mEffect.clear();
-    if (mCblk) {
-        mCblk->~effect_param_cblk_t();   // destroy our shared-structure.
-    }
-    mCblkMemory.clear();            // and free the shared memory
     if (mClient != 0) {
+        if (mCblk) {
+            mCblk->~effect_param_cblk_t();   // destroy our shared-structure.
+        }
+        mCblkMemory.clear();            // and free the shared memory
         Mutex::Autolock _l(mClient->audioFlinger()->mLock);
         mClient.clear();
     }
@@ -6643,6 +6785,7 @@
         return INVALID_OPERATION;
     }
     if (mEffect == 0) return DEAD_OBJECT;
+    if (mClient == 0) return INVALID_OPERATION;
 
     // handle commands that are not forwarded transparently to effect engine
     if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
@@ -6749,15 +6892,15 @@
 
 void AudioFlinger::EffectHandle::dump(char* buffer, size_t size)
 {
-    bool locked = tryLock(mCblk->lock);
+    bool locked = mCblk ? tryLock(mCblk->lock) : false;
 
     snprintf(buffer, size, "\t\t\t%05d %05d    %01u    %01u      %05u  %05u\n",
             (mClient == NULL) ? getpid() : mClient->pid(),
             mPriority,
             mHasControl,
             !locked,
-            mCblk->clientIndex,
-            mCblk->serverIndex
+            mCblk ? mCblk->clientIndex : 0,
+            mCblk ? mCblk->serverIndex : 0
             );
 
     if (locked) {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 4fa70a2..3a0aac9 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -149,6 +149,10 @@
 
     virtual int newAudioSessionId();
 
+    virtual void acquireAudioSessionId(int audioSession);
+
+    virtual void releaseAudioSessionId(int audioSession);
+
     virtual status_t queryNumberEffects(uint32_t *numEffects);
 
     virtual status_t queryEffect(uint32_t index, effect_descriptor_t *descriptor);
@@ -215,6 +219,7 @@
     status_t                initCheck() const;
     virtual     void        onFirstRef();
     audio_hw_device_t*      findSuitableHwDev_l(uint32_t devices);
+    void                    purgeStaleEffects_l();
 
     // Internal dump utilites.
     status_t dumpPermissionDenial(int fd, const Vector<String16>& args);
@@ -436,7 +441,8 @@
                                         int *enabled,
                                         status_t *status);
                     void disconnectEffect(const sp< EffectModule>& effect,
-                                          const wp<EffectHandle>& handle);
+                                          const wp<EffectHandle>& handle,
+                                          bool unpiniflast);
 
                     // return values for hasAudioSession (bit field)
                     enum effect_state {
@@ -519,6 +525,7 @@
                     // updated mSuspendedSessions when an effect chain is removed
                     void updateSuspendedSessionsOnRemoveEffectChain_l(const sp<EffectChain>& chain);
 
+        friend class AudioFlinger;
         friend class Track;
         friend class TrackBase;
         friend class PlaybackThread;
@@ -607,7 +614,6 @@
 
         protected:
             friend class ThreadBase;
-            friend class AudioFlinger;
             friend class TrackHandle;
             friend class PlaybackThread;
             friend class MixerThread;
@@ -1100,7 +1106,7 @@
         wp<ThreadBase>& thread() { return mThread; }
 
         status_t addHandle(sp<EffectHandle>& handle);
-        void disconnect(const wp<EffectHandle>& handle);
+        void disconnect(const wp<EffectHandle>& handle, bool unpiniflast);
         size_t removeHandle (const wp<EffectHandle>& handle);
 
         effect_descriptor_t& desc() { return mDescriptor; }
@@ -1115,9 +1121,15 @@
 
         sp<EffectHandle> controlHandle();
 
+        bool             isPinned() { return mPinned; }
+        void             unPin() { mPinned = false; }
+
         status_t         dump(int fd, const Vector<String16>& args);
 
     protected:
+        friend class EffectHandle;
+        friend class AudioFlinger;
+        bool                mPinned;
 
         // Maximum time allocated to effect engines to complete the turn off sequence
         static const uint32_t MAX_DISABLE_TIME_MS = 10000;
@@ -1169,6 +1181,7 @@
                                  uint32_t *replySize,
                                  void *pReplyData);
         virtual void disconnect();
+        virtual void disconnect(bool unpiniflast);
         virtual sp<IMemory> getCblk() const;
         virtual status_t onTransact(uint32_t code, const Parcel& data,
                 Parcel* reply, uint32_t flags);
@@ -1196,7 +1209,8 @@
         void dump(char* buffer, size_t size);
 
     protected:
-
+        friend class AudioFlinger;
+        friend class EffectModule;
         EffectHandle(const EffectHandle&);
         EffectHandle& operator =(const EffectHandle&);
 
@@ -1288,7 +1302,7 @@
         status_t dump(int fd, const Vector<String16>& args);
 
     protected:
-
+        friend class AudioFlinger;
         EffectChain(const EffectChain&);
         EffectChain& operator =(const EffectChain&);
 
@@ -1344,6 +1358,12 @@
             hwDev(dev), stream(in) {}
     };
 
+    struct AudioSessionRef {
+        int sessionid;
+        pid_t pid;
+        int cnt;
+    };
+
     friend class RecordThread;
     friend class PlaybackThread;
 
@@ -1369,6 +1389,7 @@
                 uint32_t                            mMode;
                 bool                                mBtNrec;
 
+                Vector<AudioSessionRef*> mAudioSessionRefs;
 };
 
 
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index f80be1b..5bc5f30 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -53,6 +53,7 @@
 import android.app.StatusBarManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -2467,10 +2468,13 @@
 
         // if they don't have this permission, mask out the status bar bits
         if (attrs != null) {
-            if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
-                    != PackageManager.PERMISSION_GRANTED) {
-                attrs.systemUiVisibility &= ~StatusBarManager.DISABLE_MASK;
-                attrs.subtreeSystemUiVisibility &= ~StatusBarManager.DISABLE_MASK;
+            if (((attrs.systemUiVisibility|attrs.subtreeSystemUiVisibility)
+                    & StatusBarManager.DISABLE_MASK) != 0) {
+                if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
+                        != PackageManager.PERMISSION_GRANTED) {
+                    attrs.systemUiVisibility &= ~StatusBarManager.DISABLE_MASK;
+                    attrs.subtreeSystemUiVisibility &= ~StatusBarManager.DISABLE_MASK;
+                }
             }
         }
         long origId = Binder.clearCallingIdentity();
@@ -6900,7 +6904,7 @@
                 if (ws.mRebuilding) {
                     StringWriter sw = new StringWriter();
                     PrintWriter pw = new PrintWriter(sw);
-                    ws.dump(pw, "");
+                    ws.dump(pw, "", true);
                     pw.flush();
                     Slog.w(TAG, "This window was lost: " + ws);
                     Slog.w(TAG, sw.toString());
@@ -8900,159 +8904,260 @@
         }
     }
 
-    @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump WindowManager from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid());
-            return;
-        }
-
+    void dumpInput(FileDescriptor fd, PrintWriter pw, boolean dumpAll) {
+        pw.println("WINDOW MANAGER INPUT (dumpsys window input)");
         mInputManager.dump(pw);
-        pw.println(" ");
-        
-        synchronized(mWindowMap) {
-            pw.println("Current Window Manager state:");
-            for (int i=mWindows.size()-1; i>=0; i--) {
-                WindowState w = mWindows.get(i);
+    }
+
+    void dumpPolicyLocked(FileDescriptor fd, PrintWriter pw, String[] args, boolean dumpAll) {
+        pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
+        mPolicy.dump("    ", fd, pw, args);
+    }
+
+    void dumpTokensLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll) {
+        pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
+        if (mTokenMap.size() > 0) {
+            pw.println("  All tokens:");
+            Iterator<WindowToken> it = mTokenMap.values().iterator();
+            while (it.hasNext()) {
+                WindowToken token = it.next();
+                pw.print("  Token "); pw.print(token.token);
+                if (dumpAll) {
+                    pw.println(':');
+                    token.dump(pw, "    ");
+                } else {
+                    pw.println();
+                }
+            }
+        }
+        if (mWallpaperTokens.size() > 0) {
+            pw.println();
+            pw.println("  Wallpaper tokens:");
+            for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
+                WindowToken token = mWallpaperTokens.get(i);
+                pw.print("  Wallpaper #"); pw.print(i);
+                        pw.print(' '); pw.print(token);
+                if (dumpAll) {
+                    pw.println(':');
+                    token.dump(pw, "    ");
+                } else {
+                    pw.println();
+                }
+            }
+        }
+        if (mAppTokens.size() > 0) {
+            pw.println();
+            pw.println("  Application tokens in Z order:");
+            for (int i=mAppTokens.size()-1; i>=0; i--) {
+                pw.print("  App #"); pw.print(i); pw.print(": ");
+                        pw.println(mAppTokens.get(i));
+            }
+        }
+        if (mFinishedStarting.size() > 0) {
+            pw.println();
+            pw.println("  Finishing start of application tokens:");
+            for (int i=mFinishedStarting.size()-1; i>=0; i--) {
+                WindowToken token = mFinishedStarting.get(i);
+                pw.print("  Finished Starting #"); pw.print(i);
+                        pw.print(' '); pw.print(token);
+                if (dumpAll) {
+                    pw.println(':');
+                    token.dump(pw, "    ");
+                } else {
+                    pw.println();
+                }
+            }
+        }
+        if (mExitingTokens.size() > 0) {
+            pw.println();
+            pw.println("  Exiting tokens:");
+            for (int i=mExitingTokens.size()-1; i>=0; i--) {
+                WindowToken token = mExitingTokens.get(i);
+                pw.print("  Exiting #"); pw.print(i);
+                        pw.print(' '); pw.print(token);
+                if (dumpAll) {
+                    pw.println(':');
+                    token.dump(pw, "    ");
+                } else {
+                    pw.println();
+                }
+            }
+        }
+        if (mExitingAppTokens.size() > 0) {
+            pw.println();
+            pw.println("  Exiting application tokens:");
+            for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
+                WindowToken token = mExitingAppTokens.get(i);
+                pw.print("  Exiting App #"); pw.print(i);
+                        pw.print(' '); pw.print(token);
+                if (dumpAll) {
+                    pw.println(':');
+                    token.dump(pw, "    ");
+                } else {
+                    pw.println();
+                }
+            }
+        }
+        pw.println();
+        if (mOpeningApps.size() > 0) {
+            pw.print("  mOpeningApps="); pw.println(mOpeningApps);
+        }
+        if (mClosingApps.size() > 0) {
+            pw.print("  mClosingApps="); pw.println(mClosingApps);
+        }
+        if (mToTopApps.size() > 0) {
+            pw.print("  mToTopApps="); pw.println(mToTopApps);
+        }
+        if (mToBottomApps.size() > 0) {
+            pw.print("  mToBottomApps="); pw.println(mToBottomApps);
+        }
+    }
+
+    void dumpSessionsLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll) {
+        pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
+        if (mSessions.size() > 0) {
+            Iterator<Session> it = mSessions.iterator();
+            while (it.hasNext()) {
+                Session s = it.next();
+                pw.print("  Session "); pw.print(s); pw.println(':');
+                s.dump(pw, "    ");
+            }
+        }
+    }
+
+    void dumpWindowsLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
+            ArrayList<WindowState> windows) {
+        pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
+        for (int i=mWindows.size()-1; i>=0; i--) {
+            WindowState w = mWindows.get(i);
+            if (windows == null || windows.contains(w)) {
                 pw.print("  Window #"); pw.print(i); pw.print(' ');
                         pw.print(w); pw.println(":");
-                w.dump(pw, "    ");
+                w.dump(pw, "    ", dumpAll);
             }
-            if (mInputMethodDialogs.size() > 0) {
-                pw.println(" ");
-                pw.println("  Input method dialogs:");
-                for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
-                    WindowState w = mInputMethodDialogs.get(i);
+        }
+        if (mInputMethodDialogs.size() > 0) {
+            pw.println();
+            pw.println("  Input method dialogs:");
+            for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
+                WindowState w = mInputMethodDialogs.get(i);
+                if (windows == null || windows.contains(w)) {
                     pw.print("  IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
                 }
             }
-            if (mPendingRemove.size() > 0) {
-                pw.println(" ");
-                pw.println("  Remove pending for:");
-                for (int i=mPendingRemove.size()-1; i>=0; i--) {
-                    WindowState w = mPendingRemove.get(i);
+        }
+        if (mPendingRemove.size() > 0) {
+            pw.println();
+            pw.println("  Remove pending for:");
+            for (int i=mPendingRemove.size()-1; i>=0; i--) {
+                WindowState w = mPendingRemove.get(i);
+                if (windows == null || windows.contains(w)) {
                     pw.print("  Remove #"); pw.print(i); pw.print(' ');
-                            pw.print(w); pw.println(":");
-                    w.dump(pw, "    ");
+                            pw.print(w);
+                    if (dumpAll) {
+                        pw.println(":");
+                        w.dump(pw, "    ", true);
+                    } else {
+                        pw.println();
+                    }
                 }
             }
-            if (mForceRemoves != null && mForceRemoves.size() > 0) {
-                pw.println(" ");
-                pw.println("  Windows force removing:");
-                for (int i=mForceRemoves.size()-1; i>=0; i--) {
-                    WindowState w = mForceRemoves.get(i);
-                    pw.print("  Removing #"); pw.print(i); pw.print(' ');
-                            pw.print(w); pw.println(":");
-                    w.dump(pw, "    ");
+        }
+        if (mForceRemoves != null && mForceRemoves.size() > 0) {
+            pw.println();
+            pw.println("  Windows force removing:");
+            for (int i=mForceRemoves.size()-1; i>=0; i--) {
+                WindowState w = mForceRemoves.get(i);
+                pw.print("  Removing #"); pw.print(i); pw.print(' ');
+                        pw.print(w);
+                if (dumpAll) {
+                    pw.println(":");
+                    w.dump(pw, "    ", true);
+                } else {
+                    pw.println();
                 }
             }
-            if (mDestroySurface.size() > 0) {
-                pw.println(" ");
-                pw.println("  Windows waiting to destroy their surface:");
-                for (int i=mDestroySurface.size()-1; i>=0; i--) {
-                    WindowState w = mDestroySurface.get(i);
+        }
+        if (mDestroySurface.size() > 0) {
+            pw.println();
+            pw.println("  Windows waiting to destroy their surface:");
+            for (int i=mDestroySurface.size()-1; i>=0; i--) {
+                WindowState w = mDestroySurface.get(i);
+                if (windows == null || windows.contains(w)) {
                     pw.print("  Destroy #"); pw.print(i); pw.print(' ');
-                            pw.print(w); pw.println(":");
-                    w.dump(pw, "    ");
+                            pw.print(w);
+                    if (dumpAll) {
+                        pw.println(":");
+                        w.dump(pw, "    ", true);
+                    } else {
+                        pw.println();
+                    }
                 }
             }
-            if (mLosingFocus.size() > 0) {
-                pw.println(" ");
-                pw.println("  Windows losing focus:");
-                for (int i=mLosingFocus.size()-1; i>=0; i--) {
-                    WindowState w = mLosingFocus.get(i);
+        }
+        if (mLosingFocus.size() > 0) {
+            pw.println();
+            pw.println("  Windows losing focus:");
+            for (int i=mLosingFocus.size()-1; i>=0; i--) {
+                WindowState w = mLosingFocus.get(i);
+                if (windows == null || windows.contains(w)) {
                     pw.print("  Losing #"); pw.print(i); pw.print(' ');
-                            pw.print(w); pw.println(":");
-                    w.dump(pw, "    ");
+                            pw.print(w);
+                    if (dumpAll) {
+                        pw.println(":");
+                        w.dump(pw, "    ", true);
+                    } else {
+                        pw.println();
+                    }
                 }
             }
-            if (mResizingWindows.size() > 0) {
-                pw.println(" ");
-                pw.println("  Windows waiting to resize:");
-                for (int i=mResizingWindows.size()-1; i>=0; i--) {
-                    WindowState w = mResizingWindows.get(i);
+        }
+        if (mResizingWindows.size() > 0) {
+            pw.println();
+            pw.println("  Windows waiting to resize:");
+            for (int i=mResizingWindows.size()-1; i>=0; i--) {
+                WindowState w = mResizingWindows.get(i);
+                if (windows == null || windows.contains(w)) {
                     pw.print("  Resizing #"); pw.print(i); pw.print(' ');
-                            pw.print(w); pw.println(":");
-                    w.dump(pw, "    ");
+                            pw.print(w);
+                    if (dumpAll) {
+                        pw.println(":");
+                        w.dump(pw, "    ", true);
+                    } else {
+                        pw.println();
+                    }
                 }
             }
-            if (mSessions.size() > 0) {
-                pw.println(" ");
-                pw.println("  All active sessions:");
-                Iterator<Session> it = mSessions.iterator();
-                while (it.hasNext()) {
-                    Session s = it.next();
-                    pw.print("  Session "); pw.print(s); pw.println(':');
-                    s.dump(pw, "    ");
-                }
-            }
-            if (mTokenMap.size() > 0) {
-                pw.println(" ");
-                pw.println("  All tokens:");
-                Iterator<WindowToken> it = mTokenMap.values().iterator();
-                while (it.hasNext()) {
-                    WindowToken token = it.next();
-                    pw.print("  Token "); pw.print(token.token); pw.println(':');
-                    token.dump(pw, "    ");
-                }
-            }
-            if (mWallpaperTokens.size() > 0) {
-                pw.println(" ");
-                pw.println("  Wallpaper tokens:");
-                for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
-                    WindowToken token = mWallpaperTokens.get(i);
-                    pw.print("  Wallpaper #"); pw.print(i);
-                            pw.print(' '); pw.print(token); pw.println(':');
-                    token.dump(pw, "    ");
-                }
-            }
-            if (mAppTokens.size() > 0) {
-                pw.println(" ");
-                pw.println("  Application tokens in Z order:");
-                for (int i=mAppTokens.size()-1; i>=0; i--) {
-                    pw.print("  App #"); pw.print(i); pw.print(": ");
-                            pw.println(mAppTokens.get(i));
-                }
-            }
-            if (mFinishedStarting.size() > 0) {
-                pw.println(" ");
-                pw.println("  Finishing start of application tokens:");
-                for (int i=mFinishedStarting.size()-1; i>=0; i--) {
-                    WindowToken token = mFinishedStarting.get(i);
-                    pw.print("  Finished Starting #"); pw.print(i);
-                            pw.print(' '); pw.print(token); pw.println(':');
-                    token.dump(pw, "    ");
-                }
-            }
-            if (mExitingTokens.size() > 0) {
-                pw.println(" ");
-                pw.println("  Exiting tokens:");
-                for (int i=mExitingTokens.size()-1; i>=0; i--) {
-                    WindowToken token = mExitingTokens.get(i);
-                    pw.print("  Exiting #"); pw.print(i);
-                            pw.print(' '); pw.print(token); pw.println(':');
-                    token.dump(pw, "    ");
-                }
-            }
-            if (mExitingAppTokens.size() > 0) {
-                pw.println(" ");
-                pw.println("  Exiting application tokens:");
-                for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
-                    WindowToken token = mExitingAppTokens.get(i);
-                    pw.print("  Exiting App #"); pw.print(i);
-                            pw.print(' '); pw.print(token); pw.println(':');
-                    token.dump(pw, "    ");
-                }
-            }
-            pw.println(" ");
-            pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
+        }
+        pw.println();
+        if (mDisplay != null) {
+            pw.print("  Display: init="); pw.print(mInitialDisplayWidth); pw.print("x");
+                    pw.print(mInitialDisplayHeight); pw.print(" base=");
+                    pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
+                    pw.print(" cur=");
+                    pw.print(mCurDisplayWidth); pw.print("x"); pw.print(mCurDisplayHeight);
+                    pw.print(" app=");
+                    pw.print(mAppDisplayWidth); pw.print("x"); pw.print(mAppDisplayHeight);
+                    pw.print(" raw="); pw.print(mDisplay.getRawWidth());
+                    pw.print("x"); pw.println(mDisplay.getRawHeight());
+        } else {
+            pw.println("  NO DISPLAY");
+        }
+        pw.print("  mCurConfiguration="); pw.println(this.mCurConfiguration);
+        pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
+        if (mLastFocus != mCurrentFocus) {
             pw.print("  mLastFocus="); pw.println(mLastFocus);
-            pw.print("  mFocusedApp="); pw.println(mFocusedApp);
+        }
+        pw.print("  mFocusedApp="); pw.println(mFocusedApp);
+        if (mInputMethodTarget != null) {
             pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
-            pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
+        }
+        pw.print("  mInTouchMode="); pw.print(mInTouchMode);
+                pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
+        if (dumpAll) {
+            if (mInputMethodWindow != null) {
+                pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
+            }
             pw.print("  mWallpaperTarget="); pw.println(mWallpaperTarget);
             if (mLowerWallpaperTarget != null && mUpperWallpaperTarget != null) {
                 pw.print("  mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
@@ -9061,13 +9166,19 @@
             if (mWindowDetachedWallpaper != null) {
                 pw.print("  mWindowDetachedWallpaper="); pw.println(mWindowDetachedWallpaper);
             }
+            pw.print("  mLastWallpaperX="); pw.print(mLastWallpaperX);
+                    pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
+            if (mInputMethodAnimLayerAdjustment != 0 ||
+                    mWallpaperAnimLayerAdjustment != 0) {
+                pw.print("  mInputMethodAnimLayerAdjustment=");
+                        pw.print(mInputMethodAnimLayerAdjustment);
+                        pw.print("  mWallpaperAnimLayerAdjustment=");
+                        pw.println(mWallpaperAnimLayerAdjustment);
+            }
             if (mWindowAnimationBackgroundSurface != null) {
                 pw.println("  mWindowAnimationBackgroundSurface:");
                 mWindowAnimationBackgroundSurface.printTo("    ", pw);
             }
-            pw.print("  mCurConfiguration="); pw.println(this.mCurConfiguration);
-            pw.print("  mInTouchMode="); pw.print(mInTouchMode);
-                    pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
             pw.print("  mSystemBooted="); pw.print(mSystemBooted);
                     pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
             pw.print("  mLayoutNeeded="); pw.print(mLayoutNeeded);
@@ -9078,12 +9189,6 @@
             } else {
                 pw.println( "  no DimAnimator ");
             }
-            pw.print("  mInputMethodAnimLayerAdjustment=");
-                    pw.print(mInputMethodAnimLayerAdjustment);
-                    pw.print("  mWallpaperAnimLayerAdjustment=");
-                    pw.println(mWallpaperAnimLayerAdjustment);
-            pw.print("  mLastWallpaperX="); pw.print(mLastWallpaperX);
-                    pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
             pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
                     pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen);
                     pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen);
@@ -9113,33 +9218,159 @@
             }
             pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
                     pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
-            if (mOpeningApps.size() > 0) {
-                pw.print("  mOpeningApps="); pw.println(mOpeningApps);
+        }
+    }
+
+    boolean dumpWindows(FileDescriptor fd, PrintWriter pw, String name, String[] args,
+            int opti, boolean dumpAll) {
+        ArrayList<WindowState> windows = new ArrayList<WindowState>();
+        if ("visible".equals(name)) {
+            synchronized(mWindowMap) {
+                for (int i=mWindows.size()-1; i>=0; i--) {
+                    WindowState w = mWindows.get(i);
+                    if (w.mSurfaceShown) {
+                        windows.add(w);
+                    }
+                }
             }
-            if (mClosingApps.size() > 0) {
-                pw.print("  mClosingApps="); pw.println(mClosingApps);
+        } else {
+            int objectId = 0;
+            // See if this is an object ID.
+            try {
+                objectId = Integer.parseInt(name, 16);
+                name = null;
+            } catch (RuntimeException e) {
             }
-            if (mToTopApps.size() > 0) {
-                pw.print("  mToTopApps="); pw.println(mToTopApps);
+            synchronized(mWindowMap) {
+                for (int i=mWindows.size()-1; i>=0; i--) {
+                    WindowState w = mWindows.get(i);
+                    if (name != null) {
+                        if (w.mAttrs.getTitle().toString().contains(name)) {
+                            windows.add(w);
+                        }
+                    } else if (System.identityHashCode(w) == objectId) {
+                        windows.add(w);
+                    }
+                }
             }
-            if (mToBottomApps.size() > 0) {
-                pw.print("  mToBottomApps="); pw.println(mToBottomApps);
+        }
+
+        if (windows.size() <= 0) {
+            return false;
+        }
+
+        synchronized(mWindowMap) {
+            dumpWindowsLocked(fd, pw, dumpAll, windows);
+        }
+        return true;
+    }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
+                != PackageManager.PERMISSION_GRANTED) {
+            pw.println("Permission Denial: can't dump WindowManager from from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid());
+            return;
+        }
+
+        boolean dumpAll = false;
+
+        int opti = 0;
+        while (opti < args.length) {
+            String opt = args[opti];
+            if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
+                break;
             }
-            if (mDisplay != null) {
-                pw.print("  Display: init="); pw.print(mInitialDisplayWidth); pw.print("x");
-                        pw.print(mInitialDisplayHeight); pw.print(" base=");
-                        pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
-                        pw.print(" cur=");
-                        pw.print(mCurDisplayWidth); pw.print("x"); pw.print(mCurDisplayHeight);
-                        pw.print(" app=");
-                        pw.print(mAppDisplayWidth); pw.print("x"); pw.print(mAppDisplayHeight);
-                        pw.print(" raw="); pw.print(mDisplay.getRawWidth());
-                        pw.print("x"); pw.println(mDisplay.getRawHeight());
+            opti++;
+            if ("-a".equals(opt)) {
+                dumpAll = true;
+            } else if ("-h".equals(opt)) {
+                pw.println("Window manager dump options:");
+                pw.println("  [-a] [-h] [cmd] ...");
+                pw.println("  cmd may be one of:");
+                pw.println("    i[input]: input subsystem state");
+                pw.println("    p[policy]: policy state");
+                pw.println("    s[essions]: active sessions");
+                pw.println("    t[okens]: token list");
+                pw.println("    w[indows]: window list");
+                pw.println("  cmd may also be a NAME to dump windows.  NAME may");
+                pw.println("    be a partial substring in a window name, a");
+                pw.println("    Window hex object identifier, or");
+                pw.println("    \"all\" for all windows, or");
+                pw.println("    \"visible\" for the visible windows.");
+                pw.println("  -a: include all available server state.");
+                return;
             } else {
-                pw.println("  NO DISPLAY");
+                pw.println("Unknown argument: " + opt + "; use -h for help");
             }
-            pw.println("  Policy:");
-            mPolicy.dump("    ", fd, pw, args);
+        }
+
+        // Is the caller requesting to dump a particular piece of data?
+        if (opti < args.length) {
+            String cmd = args[opti];
+            opti++;
+            if ("input".equals(cmd) || "i".equals(cmd)) {
+                dumpInput(fd, pw, true);
+                return;
+            } else if ("policy".equals(cmd) || "p".equals(cmd)) {
+                synchronized(mWindowMap) {
+                    dumpPolicyLocked(fd, pw, args, true);
+                }
+                return;
+            } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
+                synchronized(mWindowMap) {
+                    dumpSessionsLocked(fd, pw, true);
+                }
+                return;
+            } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
+                synchronized(mWindowMap) {
+                    dumpTokensLocked(fd, pw, true);
+                }
+                return;
+            } else if ("windows".equals(cmd) || "w".equals(cmd)) {
+                synchronized(mWindowMap) {
+                    dumpWindowsLocked(fd, pw, true, null);
+                }
+                return;
+            } else if ("all".equals(cmd) || "a".equals(cmd)) {
+                synchronized(mWindowMap) {
+                    dumpWindowsLocked(fd, pw, true, null);
+                }
+                return;
+            } else {
+                // Dumping a single name?
+                if (!dumpWindows(fd, pw, cmd, args, opti, dumpAll)) {
+                    pw.println("Bad window command, or no windows match: " + cmd);
+                    pw.println("Use -h for help.");
+                }
+                return;
+            }
+        }
+
+        dumpInput(fd, pw, dumpAll);
+
+        synchronized(mWindowMap) {
+            if (dumpAll) {
+                pw.println("-------------------------------------------------------------------------------");
+            }
+            dumpPolicyLocked(fd, pw, args, dumpAll);
+            pw.println();
+            if (dumpAll) {
+                pw.println("-------------------------------------------------------------------------------");
+            }
+            dumpSessionsLocked(fd, pw, dumpAll);
+            pw.println();
+            if (dumpAll) {
+                pw.println("-------------------------------------------------------------------------------");
+            }
+            dumpTokensLocked(fd, pw, dumpAll);
+            pw.println();
+            if (dumpAll) {
+                pw.println("-------------------------------------------------------------------------------");
+            }
+            dumpWindowsLocked(fd, pw, dumpAll, null);
         }
     }
 
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index cacb3e7..cdd0047 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -1511,10 +1511,13 @@
         }
     }
 
-    void dump(PrintWriter pw, String prefix) {
+    void dump(PrintWriter pw, String prefix, boolean dumpAll) {
         pw.print(prefix); pw.print("mSession="); pw.print(mSession);
                 pw.print(" mClient="); pw.println(mClient.asBinder());
         pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
+        pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
+                pw.print(" h="); pw.print(mRequestedHeight);
+                pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
         if (mAttachedWindow != null || mLayoutAttached) {
             pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
                     pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
@@ -1525,15 +1528,19 @@
                     pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer);
                     pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible);
         }
-        pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
-                pw.print(" mSubLayer="); pw.print(mSubLayer);
-                pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
-                pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
-                      : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)));
-                pw.print("="); pw.print(mAnimLayer);
-                pw.print(" mLastLayer="); pw.println(mLastLayer);
+        if (dumpAll) {
+            pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
+                    pw.print(" mSubLayer="); pw.print(mSubLayer);
+                    pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
+                    pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
+                          : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)));
+                    pw.print("="); pw.print(mAnimLayer);
+                    pw.print(" mLastLayer="); pw.println(mLastLayer);
+        }
         if (mSurface != null) {
-            pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
+            if (dumpAll) {
+                pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
+            }
             pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
                     pw.print(" layer="); pw.print(mSurfaceLayer);
                     pw.print(" alpha="); pw.print(mSurfaceAlpha);
@@ -1542,19 +1549,21 @@
                     pw.print(") "); pw.print(mSurfaceW);
                     pw.print(" x "); pw.println(mSurfaceH);
         }
-        pw.print(prefix); pw.print("mToken="); pw.println(mToken);
-        pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
-        if (mAppToken != null) {
-            pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
+        if (dumpAll) {
+            pw.print(prefix); pw.print("mToken="); pw.println(mToken);
+            pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
+            if (mAppToken != null) {
+                pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
+            }
+            if (mTargetAppToken != null) {
+                pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
+            }
+            pw.print(prefix); pw.print("mViewVisibility=0x");
+            pw.print(Integer.toHexString(mViewVisibility));
+            pw.print(" mLastHidden="); pw.print(mLastHidden);
+            pw.print(" mHaveFrame="); pw.print(mHaveFrame);
+            pw.print(" mObscured="); pw.println(mObscured);
         }
-        if (mTargetAppToken != null) {
-            pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
-        }
-        pw.print(prefix); pw.print("mViewVisibility=0x");
-                pw.print(Integer.toHexString(mViewVisibility));
-                pw.print(" mLastHidden="); pw.print(mLastHidden);
-                pw.print(" mHaveFrame="); pw.print(mHaveFrame);
-                pw.print(" mObscured="); pw.println(mObscured);
         if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
             pw.print(prefix); pw.print("mPolicyVisibility=");
                     pw.print(mPolicyVisibility);
@@ -1565,47 +1574,50 @@
         if (!mRelayoutCalled) {
             pw.print(prefix); pw.print("mRelayoutCalled="); pw.println(mRelayoutCalled);
         }
-        pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
-                pw.print(" h="); pw.print(mRequestedHeight);
-                pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
         if (mXOffset != 0 || mYOffset != 0) {
             pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
                     pw.print(" y="); pw.println(mYOffset);
         }
-        pw.print(prefix); pw.print("mGivenContentInsets=");
-                mGivenContentInsets.printShortString(pw);
-                pw.print(" mGivenVisibleInsets=");
-                mGivenVisibleInsets.printShortString(pw);
-                pw.println();
-        if (mTouchableInsets != 0 || mGivenInsetsPending) {
-            pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
-                    pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
+        if (dumpAll) {
+            pw.print(prefix); pw.print("mGivenContentInsets=");
+                    mGivenContentInsets.printShortString(pw);
+                    pw.print(" mGivenVisibleInsets=");
+                    mGivenVisibleInsets.printShortString(pw);
+                    pw.println();
+            if (mTouchableInsets != 0 || mGivenInsetsPending) {
+                pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
+                        pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
+            }
+            pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
         }
-        pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
         pw.print(prefix); pw.print("mShownFrame=");
                 mShownFrame.printShortString(pw); pw.println();
-        pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
-                pw.print(" last="); mLastFrame.printShortString(pw);
-                pw.println();
+        if (dumpAll) {
+            pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
+                    pw.print(" last="); mLastFrame.printShortString(pw);
+                    pw.println();
+        }
         if (mEnforceSizeCompat) {
             pw.print(prefix); pw.print("mCompatFrame="); mCompatFrame.printShortString(pw);
                     pw.println();
         }
-        pw.print(prefix); pw.print("mContainingFrame=");
-                mContainingFrame.printShortString(pw);
-                pw.print(" mParentFrame=");
-                mParentFrame.printShortString(pw);
-                pw.print(" mDisplayFrame=");
-                mDisplayFrame.printShortString(pw);
-                pw.println();
-        pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw);
-                pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw);
-                pw.println();
-        pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw);
-                pw.print(" last="); mLastContentInsets.printShortString(pw);
-                pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw);
-                pw.print(" last="); mLastVisibleInsets.printShortString(pw);
-                pw.println();
+        if (dumpAll) {
+            pw.print(prefix); pw.print("mContainingFrame=");
+                    mContainingFrame.printShortString(pw);
+                    pw.print(" mParentFrame=");
+                    mParentFrame.printShortString(pw);
+                    pw.print(" mDisplayFrame=");
+                    mDisplayFrame.printShortString(pw);
+                    pw.println();
+            pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw);
+                    pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw);
+                    pw.println();
+            pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw);
+                    pw.print(" last="); mLastContentInsets.printShortString(pw);
+                    pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw);
+                    pw.print(" last="); mLastVisibleInsets.printShortString(pw);
+                    pw.println();
+        }
         if (mAnimating || mLocalAnimating || mAnimationIsEntrance
                 || mAnimation != null) {
             pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
@@ -1632,10 +1644,12 @@
                     pw.print(" mDsDy="); pw.print(mDsDy);
                     pw.print(" mDtDy="); pw.println(mDtDy);
         }
-        pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending);
-                pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending);
-                pw.print(" mReadyToShow="); pw.print(mReadyToShow);
-                pw.print(" mHasDrawn="); pw.println(mHasDrawn);
+        if (dumpAll) {
+            pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending);
+                    pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending);
+                    pw.print(" mReadyToShow="); pw.print(mReadyToShow);
+                    pw.print(" mHasDrawn="); pw.println(mHasDrawn);
+        }
         if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
             pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
                     pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);