Merge "Fix more things that CloseGuard found."
diff --git a/api/current.xml b/api/current.xml
index 19c1384..357daae 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -21087,6 +21087,32 @@
 <parameter name="nonRoot" type="boolean">
 </parameter>
 </method>
+<method name="onActionModeFinished"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+</method>
+<method name="onActionModeStarted"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+</method>
 <method name="onActivityResult"
  return="void"
  abstract="false"
@@ -21722,19 +21748,6 @@
  visibility="protected"
 >
 </method>
-<method name="onStartActionMode"
- return="android.view.ActionMode"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="callback" type="android.view.ActionMode.Callback">
-</parameter>
-</method>
 <method name="onStop"
  return="void"
  abstract="false"
@@ -21835,6 +21848,19 @@
 <parameter name="hasFocus" type="boolean">
 </parameter>
 </method>
+<method name="onWindowStartingActionMode"
+ return="android.view.ActionMode"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="callback" type="android.view.ActionMode.Callback">
+</parameter>
+</method>
 <method name="openContextMenu"
  return="void"
  abstract="false"
@@ -21885,47 +21911,6 @@
 <parameter name="exitAnim" type="int">
 </parameter>
 </method>
-<method name="popBackStack"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="deprecated"
- visibility="public"
->
-</method>
-<method name="popBackStack"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="deprecated"
- visibility="public"
->
-<parameter name="name" type="java.lang.String">
-</parameter>
-<parameter name="flags" type="int">
-</parameter>
-</method>
-<method name="popBackStack"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="deprecated"
- visibility="public"
->
-<parameter name="id" type="int">
-</parameter>
-<parameter name="flags" type="int">
-</parameter>
-</method>
 <method name="registerForContextMenu"
  return="void"
  abstract="false"
@@ -22611,17 +22596,6 @@
  visibility="protected"
 >
 </field>
-<field name="POP_BACK_STACK_INCLUSIVE"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="RESULT_CANCELED"
  type="int"
  transient="false"
@@ -25434,6 +25408,32 @@
  visibility="public"
 >
 </method>
+<method name="onActionModeFinished"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+</method>
+<method name="onActionModeStarted"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+</method>
 <method name="onAttachedToWindow"
  return="void"
  abstract="false"
@@ -25784,19 +25784,6 @@
  visibility="protected"
 >
 </method>
-<method name="onStartActionMode"
- return="android.view.ActionMode"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="callback" type="android.view.ActionMode.Callback">
-</parameter>
-</method>
 <method name="onStop"
  return="void"
  abstract="false"
@@ -25860,6 +25847,19 @@
 <parameter name="hasFocus" type="boolean">
 </parameter>
 </method>
+<method name="onWindowStartingActionMode"
+ return="android.view.ActionMode"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="callback" type="android.view.ActionMode.Callback">
+</parameter>
+</method>
 <method name="openContextMenu"
  return="void"
  abstract="false"
@@ -28308,6 +28308,17 @@
 <parameter name="args" type="java.lang.String[]">
 </parameter>
 </method>
+<method name="executePendingTransactions"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="findFragmentById"
  return="android.app.Fragment"
  abstract="true"
@@ -28374,7 +28385,7 @@
 >
 </method>
 <method name="popBackStack"
- return="boolean"
+ return="void"
  abstract="true"
  native="false"
  synchronized="false"
@@ -28385,7 +28396,7 @@
 >
 </method>
 <method name="popBackStack"
- return="boolean"
+ return="void"
  abstract="true"
  native="false"
  synchronized="false"
@@ -28400,6 +28411,47 @@
 </parameter>
 </method>
 <method name="popBackStack"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="int">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<method name="popBackStackImmediate"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="popBackStackImmediate"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<method name="popBackStackImmediate"
  return="boolean"
  abstract="true"
  native="false"
@@ -212083,6 +212135,32 @@
 <parameter name="event" type="android.view.MotionEvent">
 </parameter>
 </method>
+<method name="onActionModeFinished"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+</method>
+<method name="onActionModeStarted"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+</method>
 <method name="onAttachedToWindow"
  return="void"
  abstract="true"
@@ -212217,19 +212295,6 @@
  visibility="public"
 >
 </method>
-<method name="onStartActionMode"
- return="android.view.ActionMode"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="callback" type="android.view.ActionMode.Callback">
-</parameter>
-</method>
 <method name="onWindowAttributesChanged"
  return="void"
  abstract="true"
@@ -212256,6 +212321,19 @@
 <parameter name="hasFocus" type="boolean">
 </parameter>
 </method>
+<method name="onWindowStartingActionMode"
+ return="android.view.ActionMode"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="callback" type="android.view.ActionMode.Callback">
+</parameter>
+</method>
 </interface>
 <interface name="WindowManager"
  abstract="true"
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 33f88d8..5174f19 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2086,63 +2086,12 @@
     }
     
     /**
-     * Flag for {@link #popBackStack(String, int)}
-     * and {@link #popBackStack(int, int)}: If set, and the name or ID of
-     * a back stack entry has been supplied, then all matching entries will
-     * be consumed until one that doesn't match is found or the bottom of
-     * the stack is reached.  Otherwise, all entries up to but not including that entry
-     * will be removed.
-     */
-    public static final int POP_BACK_STACK_INCLUSIVE = 1<<0;
-
-    /**
-     * Pop the top state off the back stack.  Returns true if there was one
-     * to pop, else false.
-     * @deprecated use {@link #getFragmentManager}.
-     */
-    @Deprecated
-    public boolean popBackStack() {
-        return mFragments.popBackStack();
-    }
-
-    /**
-     * Pop the last fragment transition from the local activity's fragment
-     * back stack.  If there is nothing to pop, false is returned.
-     * @param name If non-null, this is the name of a previous back state
-     * to look for; if found, all states up to that state will be popped.  The
-     * {@link #POP_BACK_STACK_INCLUSIVE} flag can be used to control whether
-     * the named state itself is popped. If null, only the top state is popped.
-     * @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}.
-     * @deprecated use {@link #getFragmentManager}.
-     */
-    @Deprecated
-    public boolean popBackStack(String name, int flags) {
-        return mFragments.popBackStack(name, flags);
-    }
-
-    /**
-     * Pop all back stack states up to the one with the given identifier.
-     * @param id Identifier of the stated to be popped. If no identifier exists,
-     * false is returned.
-     * The identifier is the number returned by
-     * {@link FragmentTransaction#commit() FragmentTransaction.commit()}.  The
-     * {@link #POP_BACK_STACK_INCLUSIVE} flag can be used to control whether
-     * the named state itself is popped.
-     * @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}.
-     * @deprecated use {@link #getFragmentManager}.
-     */
-    @Deprecated
-    public boolean popBackStack(int id, int flags) {
-        return mFragments.popBackStack(id, flags);
-    }
-    
-    /**
      * Called when the activity has detected the user's press of the back
      * key.  The default implementation simply finishes the current activity,
      * but you can override this to do whatever you want.
      */
     public void onBackPressed() {
-        if (!mFragments.popBackStack()) {
+        if (!mFragments.popBackStackImmediate()) {
             finish();
         }
     }
@@ -4174,7 +4123,7 @@
     }
 
     /**
-     * Start a context mode.
+     * Start an action mode.
      *
      * @param callback Callback that will manage lifecycle events for this context mode
      * @return The ContextMode that was started, or null if it was canceled
@@ -4185,7 +4134,18 @@
         return mWindow.getDecorView().startActionMode(callback);
     }
 
-    public ActionMode onStartActionMode(ActionMode.Callback callback) {
+    /**
+     * Give the Activity a chance to control the UI for an action mode requested
+     * by the system.
+     *
+     * <p>Note: If you are looking for a notification callback that an action mode
+     * has been started for this activity, see {@link #onActionModeStarted(ActionMode)}.</p>
+     *
+     * @param callback The callback that should control the new action mode
+     * @return The new action mode, or <code>null</code> if the activity does not want to
+     *         provide special handling for this action mode. (It will be handled by the system.)
+     */
+    public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
         initActionBar();
         if (mActionBar != null) {
             return mActionBar.startActionMode(callback);
@@ -4193,6 +4153,24 @@
         return null;
     }
 
+    /**
+     * Notifies the Activity that an action mode has been started.
+     * Activity subclasses overriding this method should call the superclass implementation.
+     *
+     * @param mode The new action mode.
+     */
+    public void onActionModeStarted(ActionMode mode) {
+    }
+
+    /**
+     * Notifies the activity that an action mode has finished.
+     * Activity subclasses overriding this method should call the superclass implementation.
+     *
+     * @param mode The action mode that just finished.
+     */
+    public void onActionModeFinished(ActionMode mode) {
+    }
+
     // ------------------ Internal API ------------------
     
     final void setParent(Activity parent) {
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 526129a..64a4d7a 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -867,13 +867,19 @@
         }
     }
 
-    public ActionMode onStartActionMode(ActionMode.Callback callback) {
+    public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
         if (mActionBar != null) {
             return mActionBar.startActionMode(callback);
         }
         return null;
     }
 
+    public void onActionModeStarted(ActionMode mode) {
+    }
+
+    public void onActionModeFinished(ActionMode mode) {
+    }
+
     /**
      * @return The activity associated with this dialog, or null if there is no associated activity.
      */
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 0741d41..6e18533 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -1036,7 +1036,7 @@
             long destinationType = getLong(getColumnIndex(Downloads.Impl.COLUMN_DESTINATION));
             if (destinationType == Downloads.Impl.DESTINATION_FILE_URI ||
                     destinationType == Downloads.Impl.DESTINATION_EXTERNAL) {
-                String localPath = getString(getColumnIndex(Downloads.Impl._DATA));
+                String localPath = getString(getColumnIndex(COLUMN_LOCAL_FILENAME));
                 if (localPath == null) {
                     return null;
                 }
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 9970418..d3a4f33 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -22,6 +22,7 @@
 import android.content.res.TypedArray;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
@@ -99,6 +100,20 @@
     public abstract FragmentTransaction openTransaction();
 
     /**
+     * After a {@link FragmentTransaction} is committed with
+     * {@link FragmentTransaction#commit FragmentTransaction.commit()}, it
+     * is scheduled to be executed asynchronously on the process's main thread.
+     * If you want to immediately executing any such pending operations, you
+     * can call this function (only from the main thread) to do so.  Note that
+     * all callbacks and other related behavior will be done from within this
+     * call, so be careful about where this is called from.
+     *
+     * @return Returns true if there were any pending transactions to be
+     * executed.
+     */
+    public abstract boolean executePendingTransactions();
+
+    /**
      * Finds a fragment that was identified by the given id either when inflated
      * from XML or as the container ID when added in a transaction.  This first
      * searches through fragments that are currently added to the manager's
@@ -132,7 +147,15 @@
      * Pop the top state off the back stack.  Returns true if there was one
      * to pop, else false.
      */
-    public abstract boolean popBackStack();
+    public abstract void popBackStack();
+
+    /**
+     * Like {@link #popBackStack()}, but performs the operation immediately
+     * inside of the call.  This is like calling {@link #executePendingTransactions()}
+     * afterwards.
+     * @return Returns true if there was something popped, else false.
+     */
+    public abstract boolean popBackStackImmediate();
 
     /**
      * Pop the last fragment transition from the manager's fragment
@@ -143,7 +166,15 @@
      * the named state itself is popped. If null, only the top state is popped.
      * @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}.
      */
-    public abstract boolean popBackStack(String name, int flags);
+    public abstract void popBackStack(String name, int flags);
+
+    /**
+     * Like {@link #popBackStack(String, int)}, but performs the operation immediately
+     * inside of the call.  This is like calling {@link #executePendingTransactions()}
+     * afterwards.
+     * @return Returns true if there was something popped, else false.
+     */
+    public abstract boolean popBackStackImmediate(String name, int flags);
 
     /**
      * Pop all back stack states up to the one with the given identifier.
@@ -155,7 +186,15 @@
      * the named state itself is popped.
      * @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}.
      */
-    public abstract boolean popBackStack(int id, int flags);
+    public abstract void popBackStack(int id, int flags);
+
+    /**
+     * Like {@link #popBackStack(int, int)}, but performs the operation immediately
+     * inside of the call.  This is like calling {@link #executePendingTransactions()}
+     * afterwards.
+     * @return Returns true if there was something popped, else false.
+     */
+    public abstract boolean popBackStackImmediate(int id, int flags);
 
     /**
      * Return the number of entries currently in the back stack.
@@ -300,17 +339,58 @@
     }
 
     @Override
-    public boolean popBackStack() {
+    public boolean executePendingTransactions() {
+        return execPendingActions();
+    }
+
+    @Override
+    public void popBackStack() {
+        enqueueAction(new Runnable() {
+            @Override public void run() {
+                popBackStackState(mActivity.mHandler, null, -1, 0);
+            }
+        }, false);
+    }
+
+    @Override
+    public boolean popBackStackImmediate() {
+        checkStateLoss();
+        executePendingTransactions();
         return popBackStackState(mActivity.mHandler, null, -1, 0);
     }
 
     @Override
-    public boolean popBackStack(String name, int flags) {
+    public void popBackStack(final String name, final int flags) {
+        enqueueAction(new Runnable() {
+            @Override public void run() {
+                popBackStackState(mActivity.mHandler, name, -1, flags);
+            }
+        }, false);
+    }
+
+    @Override
+    public boolean popBackStackImmediate(String name, int flags) {
+        checkStateLoss();
+        executePendingTransactions();
         return popBackStackState(mActivity.mHandler, name, -1, flags);
     }
 
     @Override
-    public boolean popBackStack(int id, int flags) {
+    public void popBackStack(final int id, final int flags) {
+        if (id < 0) {
+            throw new IllegalArgumentException("Bad id: " + id);
+        }
+        enqueueAction(new Runnable() {
+            @Override public void run() {
+                popBackStackState(mActivity.mHandler, null, id, flags);
+            }
+        }, false);
+    }
+
+    @Override
+    public boolean popBackStackImmediate(int id, int flags) {
+        checkStateLoss();
+        executePendingTransactions();
         if (id < 0) {
             throw new IllegalArgumentException("Bad id: " + id);
         }
@@ -849,16 +929,20 @@
         return null;
     }
     
+    private void checkStateLoss() {
+        if (mStateSaved) {
+            throw new IllegalStateException(
+                    "Can not perform this action after onSaveInstanceState");
+        }
+        if (mNoTransactionsBecause != null) {
+            throw new IllegalStateException(
+                    "Can not perform this action inside of " + mNoTransactionsBecause);
+        }
+    }
+
     public void enqueueAction(Runnable action, boolean allowStateLoss) {
         if (!allowStateLoss) {
-            if (mStateSaved) {
-                throw new IllegalStateException(
-                        "Can not perform this action after onSaveInstanceState");
-            }
-            if (mNoTransactionsBecause != null) {
-                throw new IllegalStateException(
-                        "Can not perform this action inside of " + mNoTransactionsBecause);
-            }
+            checkStateLoss();
         }
         synchronized (this) {
             if (mActivity == null) {
@@ -934,17 +1018,23 @@
     /**
      * Only call from main thread!
      */
-    public void execPendingActions() {
+    public boolean execPendingActions() {
         if (mExecutingActions) {
-            throw new IllegalStateException("Recursive entry to execPendingActions");
+            throw new IllegalStateException("Recursive entry to executePendingTransactions");
         }
         
+        if (Looper.myLooper() != Looper.getMainLooper()) {
+            throw new IllegalStateException("Must be called from main thread of process");
+        }
+
+        boolean didSomething = false;
+
         while (true) {
             int numActions;
             
             synchronized (this) {
                 if (mPendingActions == null || mPendingActions.size() == 0) {
-                    return;
+                    return didSomething;
                 }
                 
                 numActions = mPendingActions.size();
@@ -961,6 +1051,7 @@
                 mTmpActions[i].run();
             }
             mExecutingActions = false;
+            didSomething = true;
         }
     }
     
@@ -984,19 +1075,14 @@
         if (mBackStack == null) {
             return false;
         }
-        if (name == null && id < 0 && (flags&Activity.POP_BACK_STACK_INCLUSIVE) == 0) {
+        if (name == null && id < 0 && (flags&POP_BACK_STACK_INCLUSIVE) == 0) {
             int last = mBackStack.size()-1;
             if (last < 0) {
                 return false;
             }
             final BackStackRecord bss = mBackStack.remove(last);
-            enqueueAction(new Runnable() {
-                public void run() {
-                    if (DEBUG) Log.v(TAG, "Popping back stack state: " + bss);
-                    bss.popFromBackStack(true);
-                    reportBackStackChanged();
-                }
-            }, false);
+            bss.popFromBackStack(true);
+            reportBackStackChanged();
         } else {
             int index = -1;
             if (name != null || id >= 0) {
@@ -1016,7 +1102,7 @@
                 if (index < 0) {
                     return false;
                 }
-                if ((flags&Activity.POP_BACK_STACK_INCLUSIVE) != 0) {
+                if ((flags&POP_BACK_STACK_INCLUSIVE) != 0) {
                     index--;
                     // Consume all following entries that match.
                     while (index >= 0) {
@@ -1038,16 +1124,12 @@
             for (int i=mBackStack.size()-1; i>index; i--) {
                 states.add(mBackStack.remove(i));
             }
-            enqueueAction(new Runnable() {
-                public void run() {
-                    final int LAST = states.size()-1;
-                    for (int i=0; i<=LAST; i++) {
-                        if (DEBUG) Log.v(TAG, "Popping back stack state: " + states.get(i));
-                        states.get(i).popFromBackStack(i == LAST);
-                    }
-                    reportBackStackChanged();
-                }
-            }, false);
+            final int LAST = states.size()-1;
+            for (int i=0; i<=LAST; i++) {
+                if (DEBUG) Log.v(TAG, "Popping back stack state: " + states.get(i));
+                states.get(i).popFromBackStack(i == LAST);
+            }
+            reportBackStackChanged();
         }
         return true;
     }
@@ -1084,6 +1166,10 @@
     }
     
     Parcelable saveAllState() {
+        // Make sure all pending operations have now been executed to get
+        // our state update-to-date.
+        execPendingActions();
+
         mStateSaved = true;
 
         if (mActive == null || mActive.size() <= 0) {
diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java
index a47c66a..47a7696 100644
--- a/core/java/android/os/DropBoxManager.java
+++ b/core/java/android/os/DropBoxManager.java
@@ -169,7 +169,12 @@
                 is = getInputStream();
                 if (is == null) return null;
                 byte[] buf = new byte[maxBytes];
-                return new String(buf, 0, Math.max(0, is.read(buf)));
+                int readBytes = 0;
+                int n = 0;
+                while (n >= 0 && (readBytes += n) < maxBytes) {
+                    n = is.read(buf, readBytes, maxBytes - readBytes);
+                }
+                return new String(buf, 0, readBytes);
             } catch (IOException e) {
                 return null;
             } finally {
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 8762512..97f015b 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -106,6 +106,8 @@
     private static final String TAG = "StrictMode";
     private static final boolean LOG_V = false;
 
+    private static final boolean IS_USER_BUILD = "user".equals(Build.TYPE);
+
     // Only log a duplicate stack trace to the logs every second.
     private static final long MIN_LOG_INTERVAL_MS = 1000;
 
@@ -693,7 +695,7 @@
     public static boolean conditionallyEnableDebugLogging() {
         // For debug builds, log event loop stalls to dropbox for analysis.
         // Similar logic also appears in ActivityThread.java for system apps.
-        if ("user".equals(Build.TYPE)) {
+        if (IS_USER_BUILD) {
             setCloseGuardEnabled(false);
             return false;
         }
@@ -1240,6 +1242,11 @@
             mContainerState = threadState;
         }
 
+        // Empty constructor for the NO_OP_SPAN
+        protected Span() {
+            mContainerState = null;
+        }
+
         /**
          * To be called when the critical span is complete (i.e. the
          * animation is done animating).  This can be called on any
@@ -1286,6 +1293,13 @@
         }
     }
 
+    // The no-op span that's used in user builds.
+    private static final Span NO_OP_SPAN = new Span() {
+            public void finish() {
+                // Do nothing.
+            }
+        };
+
     /**
      * Linked lists of active spans and a freelist.
      *
@@ -1327,6 +1341,9 @@
      * @hide
      */
     public static Span enterCriticalSpan(String name) {
+        if (IS_USER_BUILD) {
+            return NO_OP_SPAN;
+        }
         if (name == null || name.isEmpty()) {
             throw new IllegalArgumentException("name must be non-null and non-empty");
         }
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 0ce69ad..39f3cee 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -23,6 +23,7 @@
 
 import android.app.Fragment;
 import android.app.FragmentBreadCrumbs;
+import android.app.FragmentManager;
 import android.app.FragmentTransaction;
 import android.app.ListActivity;
 import android.content.Context;
@@ -902,7 +903,8 @@
     }
 
     private void switchToHeaderInner(String fragmentName, Bundle args, int direction) {
-        getFragmentManager().popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE);
+        getFragmentManager().popBackStack(BACK_STACK_PREFS,
+                FragmentManager.POP_BACK_STACK_INCLUSIVE);
         Fragment f = Fragment.instantiate(this, fragmentName, args);
         FragmentTransaction transaction = getFragmentManager().openTransaction();
         transaction.setTransition(direction == 0 ? FragmentTransaction.TRANSIT_NONE
@@ -934,7 +936,8 @@
         if (mCurHeader == header) {
             // This is the header we are currently displaying.  Just make sure
             // to pop the stack up to its root state.
-            getFragmentManager().popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE);
+            getFragmentManager().popBackStack(BACK_STACK_PREFS,
+                    FragmentManager.POP_BACK_STACK_INCLUSIVE);
         } else {
             int direction = mHeaders.indexOf(header) - mHeaders.indexOf(mCurHeader);
             switchToHeaderInner(header.fragment, header.fragmentArguments, direction);
@@ -1061,14 +1064,14 @@
             setResult(resultCode, resultData);
             finish();
         } else {
+            // XXX be smarter about popping the stack.
+            onBackPressed();
             if (caller != null) {
                 if (caller.getTargetFragment() != null) {
                     caller.getTargetFragment().onActivityResult(caller.getTargetRequestCode(),
                             resultCode, resultData);
                 }
             }
-            // XXX be smarter about popping the stack.
-            onBackPressed();
         }
     }
     
diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java
index 99da43b..602c765 100644
--- a/core/java/android/view/MenuItem.java
+++ b/core/java/android/view/MenuItem.java
@@ -405,6 +405,11 @@
     
     /**
      * Sets how this item should display in the presence of an Action Bar.
+     * The parameter actionEnum is a flag set. One of {@link #SHOW_AS_ACTION_ALWAYS},
+     * {@link #SHOW_AS_ACTION_IF_ROOM}, or {@link #SHOW_AS_ACTION_NEVER} should
+     * be used, and you may optionally OR the value with {@link #SHOW_AS_ACTION_WITH_TEXT}.
+     * SHOW_AS_ACTION_WITH_TEXT requests that when the item is shown as an action,
+     * it should be shown with a text label.
      *
      * @param actionEnum How the item should display. One of
      * {@link #SHOW_AS_ACTION_ALWAYS}, {@link #SHOW_AS_ACTION_IF_ROOM}, or
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index be49255..e6eb46e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6304,12 +6304,7 @@
             }
             final AttachInfo ai = mAttachInfo;
             final ViewParent p = mParent;
-            if (p != null && ai != null && ai.mHardwareAccelerated) {
-                // fast-track for GL-enabled applications; just invalidate the whole hierarchy
-                // with a null dirty rect, which tells the ViewRoot to redraw everything
-                p.invalidateChild(this, null);
-                return;
-            }
+
             if (p != null && ai != null) {
                 final Rect r = ai.mTmpInvalRect;
                 r.set(0, 0, mRight - mLeft, mBottom - mTop);
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index d5d9a2e..5385cd9 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -313,12 +313,31 @@
         public boolean onSearchRequested();
 
         /**
-         * Called when an action mode is being started.
+         * Called when an action mode is being started for this window. Gives the
+         * callback an opportunity to handle the action mode in its own unique and
+         * beautiful way. If this method returns null the system can choose a way
+         * to present the mode or choose not to start the mode at all.
          *
          * @param callback Callback to control the lifecycle of this action mode
-         * @return The ActionMode that was started, or null if it was canceled
+         * @return The ActionMode that was started, or null if the system should present it
          */
-        public ActionMode onStartActionMode(ActionMode.Callback callback);
+        public ActionMode onWindowStartingActionMode(ActionMode.Callback callback);
+
+        /**
+         * Called when an action mode has been started. The appropriate mode callback
+         * method will have already been invoked.
+         *
+         * @param mode The new mode that has just been started.
+         */
+        public void onActionModeStarted(ActionMode mode);
+
+        /**
+         * Called when an action mode has been finished. The appropriate mode callback
+         * method will have already been invoked.
+         *
+         * @param mode The mode that was just finished.
+         */
+        public void onActionModeFinished(ActionMode mode);
     }
 
     public Window(Context context) {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 14dbfe2..06800d5 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2384,7 +2384,6 @@
 
     Rect sendOurVisibleRect() {
         if (mZoomManager.isPreventingWebkitUpdates()) return mLastVisibleRectSent;
-
         Rect rect = new Rect();
         calcOurContentVisibleRect(rect);
         // Rect.equals() checks for null input.
@@ -2937,7 +2936,8 @@
             postInvalidate();  // So we draw again
             if (oldX != mScrollX || oldY != mScrollY) {
                 onScrollChanged(mScrollX, mScrollY, oldX, oldY);
-            } else {
+            } else if (mScroller.getStartX() != mScrollX
+                    || mScroller.getStartY() != mScrollY) {
                 abortAnimation();
                 mPrivateHandler.removeMessages(RESUME_WEBCORE_PRIORITY);
                 WebViewCore.resumePriority();
@@ -2970,6 +2970,7 @@
         if ((dx | dy) == 0) {
             return false;
         }
+        abortAnimation();
         if (animate) {
             //        Log.d(LOGTAG, "startScroll: " + dx + " " + dy);
             mScroller.startScroll(mScrollX, mScrollY, dx, dy,
@@ -2977,7 +2978,6 @@
             awakenScrollBars(mScroller.getDuration());
             invalidate();
         } else {
-            abortAnimation(); // just in case
             scrollTo(x, y);
         }
         return true;
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 23f8bd9..69db6b2 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -813,7 +813,9 @@
                 setZoomOverviewWidth(Math.min(WebView.sMaxViewportWidth,
                     Math.max((int) (viewWidth * mInvDefaultScale),
                             Math.max(drawData.mMinPrefWidth, drawData.mViewSize.x))));
-            } else {
+            } else if (drawData.mContentSize.x > 0) {
+                // The webkitDraw for layers will not populate contentSize, and it'll be
+                // ignored for zoom overview width update.
                 final int contentWidth = Math.max(drawData.mContentSize.x, drawData.mMinPrefWidth);
                 final int newZoomOverviewWidth = Math.min(WebView.sMaxViewportWidth, contentWidth);
                 if (newZoomOverviewWidth != mZoomOverviewWidth) {
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index ab5ff3d..30b1e5d 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2893,8 +2893,8 @@
     void reportScrollStateChange(int newState) {
         if (newState != mLastScrollState) {
             if (mOnScrollListener != null) {
-                mOnScrollListener.onScrollStateChanged(this, newState);
                 mLastScrollState = newState;
+                mOnScrollListener.onScrollStateChanged(this, newState);
             }
         }
     }
@@ -3431,12 +3431,13 @@
     public void smoothScrollBy(int distance, int duration) {
         if (mFlingRunnable == null) {
             mFlingRunnable = new FlingRunnable();
-        } else {
-            mFlingRunnable.endFling();
         }
         // No sense starting to scroll if we're not going anywhere
         if (distance != 0) {
+            reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
             mFlingRunnable.startScroll(distance, duration);
+        } else {
+            mFlingRunnable.endFling();
         }
     }
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5320b10..b143325 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3869,7 +3869,7 @@
         // - ExtractEditText does not call onFocus when it is displayed. Fixing this issue would
         //   allow to test for hasSelection in onFocusChanged, which would trigger a
         //   startTextSelectionMode here. TODO
-        if (selectionController != null && hasSelection()) {
+        if (this instanceof ExtractEditText && selectionController != null && hasSelection()) {
             startSelectionActionMode();
         }
 
@@ -5042,6 +5042,7 @@
     }
 
     public void beginBatchEdit() {
+        mInBatchEditControllers = true;
         final InputMethodState ims = mInputMethodState;
         if (ims != null) {
             int nesting = ++ims.mBatchEditNesting;
@@ -5064,6 +5065,7 @@
     }
     
     public void endBatchEdit() {
+        mInBatchEditControllers = false;
         final InputMethodState ims = mInputMethodState;
         if (ims != null) {
             int nesting = --ims.mBatchEditNesting;
@@ -6991,26 +6993,21 @@
                 // Restore previous selection
                 Selection.setSelection((Spannable)mText, prevStart, prevEnd);
 
-                if (mSelectionModifierCursorController != null &&
-                        !mSelectionModifierCursorController.isShowing()) {
+                if (hasSelectionController() && !getSelectionController().isShowing()) {
                     // If the anchors aren't showing, revive them.
-                    mSelectionModifierCursorController.show();
-                } else {
-                    // Tapping inside the selection displays the cut/copy/paste context menu
-                    // as long as the anchors are already showing.
-                    showContextMenu();
+                    getSelectionController().show();
                 }
                 return;
             } else {
                 // Tapping outside stops selection mode, if any
                 stopSelectionActionMode();
 
-                if (mInsertionPointCursorController != null) {
-                    mInsertionPointCursorController.show();
+                if (hasInsertionController()) {
+                    getInsertionController().show();
                 }
             }
-        } else if (hasSelection() && mSelectionModifierCursorController != null) {
-            mSelectionModifierCursorController.show();
+        } else if (hasSelection() && hasSelectionController()) {
+            getSelectionController().show();
         }
     }
 
@@ -7043,11 +7040,12 @@
     @Override
     public boolean onTouchEvent(MotionEvent event) {
         final int action = event.getActionMasked();
-        if (mInsertionPointCursorController != null) {
-            mInsertionPointCursorController.onTouchEvent(event);
+
+        if (hasInsertionController()) {
+            getInsertionController().onTouchEvent(event);
         }
-        if (mSelectionModifierCursorController != null) {
-            mSelectionModifierCursorController.onTouchEvent(event);
+        if (hasSelectionController()) {
+            getSelectionController().onTouchEvent(event);
         }
 
         if (action == MotionEvent.ACTION_DOWN) {
@@ -7129,21 +7127,17 @@
                     || windowParams.type > WindowManager.LayoutParams.LAST_SUB_WINDOW;
         }
 
-        if (windowSupportsHandles && isTextEditable() && mCursorVisible && mLayout != null &&
-                !mTextIsSelectable) {
-            if (mInsertionPointCursorController == null) {
-                mInsertionPointCursorController = new InsertionPointCursorController();
-            }
-        } else {
-            hideInsertionPointCursorController();
+        // TODO Add an extra android:cursorController flag to disable the controller?
+        mInsertionControllerEnabled = windowSupportsHandles && isTextEditable() && mCursorVisible &&
+                mLayout != null && !mTextIsSelectable;
+        mSelectionControllerEnabled = windowSupportsHandles && textCanBeSelected() &&
+                mLayout != null;
+
+        if (!mInsertionControllerEnabled) {
             mInsertionPointCursorController = null;
         }
 
-        if (windowSupportsHandles && textCanBeSelected() && mLayout != null) {
-            if (mSelectionModifierCursorController == null) {
-                mSelectionModifierCursorController = new SelectionModifierCursorController();
-            }
-        } else {
+        if (!mSelectionControllerEnabled) {
             // Stop selection mode if the controller becomes unavailable.
             if (mSelectionModifierCursorController != null) {
                 stopSelectionActionMode();
@@ -8348,6 +8342,10 @@
                 return true;
             }
 
+            if (isInBatchEditMode()) {
+                return false;
+            }
+
             final int extendedPaddingTop = getExtendedPaddingTop();
             final int extendedPaddingBottom = getExtendedPaddingBottom();
             final int compoundPaddingLeft = getCompoundPaddingLeft();
@@ -8387,7 +8385,7 @@
             mPositionY = y - TextView.this.mScrollY;
             if (isPositionVisible()) {
                 int[] coords = null;
-                if (mContainer.isShowing()){
+                if (mContainer.isShowing()) {
                     coords = mTempCoords;
                     TextView.this.getLocationInWindow(coords);
                     final int containerPositionX = coords[0] + mPositionX;
@@ -8626,6 +8624,10 @@
         }
 
         public void show() {
+            if (isInBatchEditMode()) {
+                return;
+            }
+
             mIsShowing = true;
             updatePosition();
             mStartHandle.show();
@@ -8689,6 +8691,10 @@
         }
 
         public void updatePosition() {
+            if (!isShowing()) {
+                return;
+            }
+
             final int selectionStart = getSelectionStart();
             final int selectionEnd = getSelectionEnd();
 
@@ -8913,8 +8919,62 @@
         }
     }
 
+    /**
+     * @return True if this view supports insertion handles.
+     */
+    boolean hasInsertionController() {
+        return mInsertionControllerEnabled;
+    }
 
-    @ViewDebug.ExportedProperty(category = "text")
+    /**
+     * @return True if this view supports selection handles.
+     */
+    boolean hasSelectionController() {
+        return mSelectionControllerEnabled;
+    }
+
+    CursorController getInsertionController() {
+        if (!mInsertionControllerEnabled) {
+            return null;
+        }
+
+        if (mInsertionPointCursorController == null) {
+            mInsertionPointCursorController = new InsertionPointCursorController();
+
+            final ViewTreeObserver observer = getViewTreeObserver();
+            if (observer != null) {
+                observer.addOnTouchModeChangeListener(mInsertionPointCursorController);
+            }
+        }
+
+        return mInsertionPointCursorController;
+    }
+
+    CursorController getSelectionController() {
+        if (!mSelectionControllerEnabled) {
+            return null;
+        }
+
+        if (mSelectionModifierCursorController == null) {
+            mSelectionModifierCursorController = new SelectionModifierCursorController();
+
+            final ViewTreeObserver observer = getViewTreeObserver();
+            if (observer != null) {
+                observer.addOnTouchModeChangeListener(mSelectionModifierCursorController);
+            }
+        }
+
+        return mSelectionModifierCursorController;
+    }
+
+    boolean isInBatchEditMode() {
+        final InputMethodState ims = mInputMethodState;
+        if (ims != null) {
+            return ims.mBatchEditNesting > 0;
+        }
+        return mInBatchEditControllers;
+    }
+
     private CharSequence            mText;
     private CharSequence            mTransformed;
     private BufferType              mBufferType = BufferType.NORMAL;
@@ -8942,10 +9002,14 @@
     private Blink                   mBlink;
     private boolean                 mCursorVisible = true;
 
-    // Cursor Controllers. Null when disabled.
+    // Cursor Controllers.
     private CursorController        mInsertionPointCursorController;
     private CursorController        mSelectionModifierCursorController;
     private ActionMode              mSelectionActionMode;
+    private boolean                 mInsertionControllerEnabled;
+    private boolean                 mSelectionControllerEnabled;
+    private boolean                 mInBatchEditControllers;
+
     // These are needed to desambiguate a long click. If the long click comes from ones of these, we
     // select from the current cursor position. Otherwise, select from long pressed position.
     private boolean                 mDPadCenterIsDown = false;
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 1d103ed..1406e4e 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -110,8 +110,10 @@
         if (isShowing()) {
             mPopup.dismiss();
         }
-        mTreeObserver.removeGlobalOnLayoutListener(this);
-        mTreeObserver = null;
+        if (mTreeObserver != null) {
+            mTreeObserver.removeGlobalOnLayoutListener(this);
+            mTreeObserver = null;
+        }
     }
 
     public boolean isShowing() {
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 0a4f543..e18f58f 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -40,6 +40,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewParent;
+import android.view.Window;
 import android.widget.AdapterView;
 import android.widget.HorizontalScrollView;
 import android.widget.ImageView;
@@ -219,7 +220,7 @@
             Context context = getContext();
             if (context instanceof Activity) {
               Activity activity = (Activity) context;
-              activity.onOptionsItemSelected(mLogoNavItem);
+              activity.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, mLogoNavItem);
             }
           }
         });
diff --git a/core/tests/ConnectivityManagerTest/assets/accesspoints.xml b/core/tests/ConnectivityManagerTest/assets/accesspoints.xml
new file mode 100755
index 0000000..2b0e4af
--- /dev/null
+++ b/core/tests/ConnectivityManagerTest/assets/accesspoints.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+  <accesspoint>
+    <ssid>opennet</ssid>
+    <security>NONE</security>
+  </accesspoint>
+    <accesspoint>
+    <ssid>GoogleGuest</ssid>
+    <security>NONE</security>
+  </accesspoint>
+  <accesspoint>
+    <ssid>securenetdhcp</ssid>
+    <security>PSK</security>
+    <password>androidwifi</password>
+  </accesspoint>
+  <accesspoint>
+    <ssid>botnet</ssid>
+    <security>EAP</security>
+    <eap>PEAP</eap>
+    <phase2>MSCHAPV2</phase2>
+    <identity>donut</identity>
+    <password>android</password>
+  </accesspoint>
+</resources>
+
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
new file mode 100644
index 0000000..863fbe6
--- /dev/null
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2010, 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 com.android.connectivitymanagertest;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.AuthAlgorithm;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+
+import android.util.Log;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * Help class to process configurations of access points saved in an XML file.
+ * The configurations of an access point is included in tag
+ * <accesspoint></accesspoint>. The supported configuration includes: ssid,
+ * security, eap, phase2, identity, password, anonymousidentity, cacert, usercert,
+ * in which each is included in the corresponding tags. All access points have to be
+ * enclosed in tags of <resources></resources>.
+ *
+ * The following is a sample configuration file for an access point using EAP-PEAP with MSCHAP2.
+ * <resources>
+ *   <accesspoint>
+ *   <ssid>testnet</ssid>
+ *   <security>EAP</security>
+ *   <eap>PEAP</eap>
+ *   <phase2>MSCHAP2</phase2>
+ *   <identity>donut</identity</identity>
+ *   <password>abcdefgh</password>
+ *   </accesspoint>
+ * </resources>
+ */
+public class AccessPointParserHelper {
+    private static final String KEYSTORE_SPACE = "keystore://";
+    private static final String TAG = "AccessPointParserHelper";
+    static final int NONE = 0;
+    static final int WEP = 1;
+    static final int PSK = 2;
+    static final int EAP = 3;
+
+    List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
+
+    private int getSecurityType (String security) {
+        if (security.equalsIgnoreCase("NONE")) {
+            return NONE;
+        } else if (security.equalsIgnoreCase("WEP")) {
+            return WEP;
+        } else if (security.equalsIgnoreCase("PSK")) {
+            return PSK;
+        } else if (security.equalsIgnoreCase("EAP")) {
+            return EAP;
+        } else {
+            return -1;
+        }
+    }
+
+    private boolean validateEapValue(String value) {
+        if (value.equalsIgnoreCase("PEAP") ||
+                value.equalsIgnoreCase("TLS") ||
+                value.equalsIgnoreCase("TTLS")) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    DefaultHandler mHandler = new DefaultHandler() {
+
+        boolean ssid = false;
+        boolean security = false;
+        boolean password = false;
+        boolean ip = false;
+        boolean subnetmask = false;
+        boolean gateway = false;
+        boolean dns = false;
+        boolean eap = false;
+        boolean phase2 = false;
+        boolean identity = false;
+        boolean anonymousidentity = false;
+        boolean cacert = false;
+        boolean usercert = false;
+        WifiConfiguration config = null;
+        int securityType = NONE;
+
+        @Override
+        public void startElement(String uri, String localName, String tagName,
+                Attributes attributes) throws SAXException {
+            if (tagName.equalsIgnoreCase("accesspoint")) {
+                config = new WifiConfiguration();
+            }
+            if (tagName.equalsIgnoreCase("ssid")) {
+                ssid = true;
+            }
+            if (tagName.equalsIgnoreCase("security")) {
+                security = true;
+            }
+            if (tagName.equalsIgnoreCase("password")) {
+                password = true;
+            }
+            if (tagName.equalsIgnoreCase("eap")) {
+                eap = true;
+            }
+            if (tagName.equalsIgnoreCase("phase2")) {
+                phase2 = true;
+            }
+            if (tagName.equalsIgnoreCase("identity")) {
+                identity = true;
+            }
+            if (tagName.equalsIgnoreCase("anonymousidentity")) {
+                anonymousidentity = true;
+            }
+            if (tagName.equalsIgnoreCase("cacert")) {
+                cacert = true;
+            }
+            if (tagName.equalsIgnoreCase("usercert")) {
+                usercert = true;
+            }
+        }
+
+        @Override
+        public void endElement(String uri, String localName, String tagName) throws SAXException {
+            Log.v(TAG, "endElement: " + tagName);
+            if (tagName.equalsIgnoreCase("accesspoint")) {
+                networks.add(config);
+            }
+        }
+
+        @Override
+        public void characters(char ch[], int start, int length) throws SAXException {
+            if (ssid) {
+                config.SSID = new String(ch, start, length);
+                Log.v(TAG, "ssid: " + config.SSID);
+                ssid = false;
+            }
+            if (security) {
+                String securityStr = (new String(ch, start, length)).toUpperCase();
+                Log.v(TAG, "security: " + securityStr);
+                securityType = getSecurityType(securityStr);
+                Log.v(TAG, "securityType = " + securityType);
+                switch (securityType) {
+                    case NONE:
+                        config.allowedKeyManagement.set(KeyMgmt.NONE);
+                        break;
+                    case WEP:
+                        config.allowedKeyManagement.set(KeyMgmt.NONE);
+                        config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
+                        config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
+                        break;
+                    case PSK:
+                        config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+                        break;
+                    case EAP:
+                        config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
+                        config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
+                        break;
+                    default:
+                        throw new SAXException();
+                }
+                security = false;
+            }
+            if (password) {
+                String passwordStr = new String(ch, start, length);
+                int len = passwordStr.length();
+                if (len == 0) {
+                    throw new SAXException();
+                }
+                Log.v(TAG, "passwordStr:" + passwordStr);
+                if (securityType == WEP) {
+                    if ((len == 10 || len == 26 || len == 58) &&
+                            passwordStr.matches("[0-9A-Fa-f]*")) {
+                        config.wepKeys[0] = passwordStr;
+                    } else {
+                        config.wepKeys[0] = '"' + passwordStr + '"';
+                    }
+                } else if (securityType == PSK) {
+                    if (passwordStr.matches("[0-9A-Fa-f]{64}")) {
+                        config.preSharedKey = passwordStr;
+                    } else {
+                        config.preSharedKey = '"' + passwordStr + '"';
+                    }
+                } else if (securityType == EAP) {
+                    config.password.setValue(passwordStr);
+                } else {
+                    throw new SAXException();
+                }
+                password = false;
+            }
+            if (eap) {
+                String eapValue = new String(ch, start, length);
+                if (!validateEapValue(eapValue)) {
+                    throw new SAXException();
+                }
+                config.eap.setValue(eapValue);
+                eap = false;
+            }
+            if (phase2) {
+                String phase2Value = new String(ch, start, length);
+                config.phase2.setValue("auth=" + phase2Value);
+                phase2 = false;
+            }
+            if (identity) {
+                String identityValue = new String(ch, start, length);
+                config.identity.setValue(identityValue);
+                identity = false;
+            }
+            if (anonymousidentity) {
+                String anonyId = new String(ch, start, length);
+                config.anonymous_identity.setValue(anonyId);
+                anonymousidentity = false;
+            }
+            if (cacert) {
+                String cacertValue = new String(ch, start, length);
+                // need to install the credentail to "keystore://"
+                config.ca_cert.setValue(KEYSTORE_SPACE);
+                cacert = false;
+            }
+            if (usercert) {
+                String usercertValue = new String(ch, start, length);
+                config.client_cert.setValue(KEYSTORE_SPACE);
+                usercert = false;
+            }
+        }
+    };
+
+    public AccessPointParserHelper() {
+    }
+
+    /**
+     * Process the accesspoint.xml file
+     * @return List of WifiConfiguration
+     * @throws Exception when parsing the XML file
+     */
+    public List<WifiConfiguration> processAccessPoint(InputStream in) throws Exception {
+        SAXParserFactory factory = SAXParserFactory.newInstance();
+        SAXParser saxParser = factory.newSAXParser();
+        saxParser.parse(in, mHandler);
+        return networks;
+    }
+}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
index e42b657..7c46e7a 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
@@ -16,8 +16,10 @@
 
 package com.android.connectivitymanagertest;
 
+import com.android.connectivitymanagertest.R;
 import android.app.Activity;
 import android.content.Context;
+import android.content.res.Resources;
 import android.content.BroadcastReceiver;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -25,19 +27,22 @@
 import android.provider.Settings;
 import android.util.Log;
 import android.view.KeyEvent;
+
+import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.List;
 import android.widget.LinearLayout;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.State;
 
+import android.net.wifi.SupplicantState;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
 
-
 /**
  * An activity registered with connectivity manager broadcast
  * provides network connectivity information and
@@ -46,8 +51,11 @@
 public class ConnectivityManagerTestActivity extends Activity {
 
     public static final String LOG_TAG = "ConnectivityManagerTestActivity";
-    public static final int WAIT_FOR_SCAN_RESULT = 5 * 1000; //5 seconds
+    public static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; //10 seconds
     public static final int WIFI_SCAN_TIMEOUT = 20 * 1000;
+    public static final int SHORT_TIMEOUT = 5 * 1000;
+    public static final long LONG_TIMEOUT = 50 * 1000;
+    private static final String ACCESS_POINT_FILE = "accesspoints.xml";
     public ConnectivityReceiver mConnectivityReceiver = null;
     public WifiReceiver mWifiReceiver = null;
     /*
@@ -175,6 +183,7 @@
         mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
         mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
         mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+        mIntentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
         registerReceiver(mWifiReceiver, mIntentFilter);
 
         // Get an instance of ConnectivityManager
@@ -185,10 +194,26 @@
 
         if (mWifiManager.isWifiEnabled()) {
             Log.v(LOG_TAG, "Clear Wifi before we start the test.");
-            clearWifi();
+            removeConfiguredNetworksAndDisableWifi();
         }
      }
 
+    public List<WifiConfiguration> loadNetworkConfigurations() throws Exception {
+        InputStream in = getAssets().open(ACCESS_POINT_FILE);
+        AccessPointParserHelper parseHelper = new AccessPointParserHelper();
+        return parseHelper.processAccessPoint(in);
+    }
+
+    private void printNetConfig(String[] configuration) {
+        for (int i = 0; i < configuration.length; i++) {
+            if (i == 0) {
+                Log.v(LOG_TAG, "SSID: " + configuration[0]);
+            } else {
+                Log.v(LOG_TAG, "      " + configuration[i]);
+            }
+        }
+    }
+
     // for each network type, initialize network states to UNKNOWN, and no verification flag is set
     public void initializeNetworkStates() {
         for (int networkType = NUM_NETWORK_TYPES - 1; networkType >=0; networkType--) {
@@ -245,6 +270,68 @@
         }
     }
 
+    // Wait for network connectivity state: CONNECTING, CONNECTED, SUSPENDED,
+    //                                      DISCONNECTING, DISCONNECTED, UNKNOWN
+    public boolean waitForNetworkState(int networkType, State expectedState, long timeout) {
+        long startTime = System.currentTimeMillis();
+        while (true) {
+            if ((System.currentTimeMillis() - startTime) > timeout) {
+                if (mCM.getNetworkInfo(networkType).getState() != expectedState) {
+                    return false;
+                } else {
+                    // the broadcast has been sent out. the state has been changed.
+                    Log.v(LOG_TAG, "networktype: " + networkType + " state: " +
+                            mCM.getNetworkInfo(networkType));
+                    return true;
+                }
+            }
+            Log.v(LOG_TAG, "Wait for the connectivity state for network: " + networkType +
+                    " to be " + expectedState.toString());
+            synchronized (connectivityObject) {
+                try {
+                    connectivityObject.wait(SHORT_TIMEOUT);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+                if ((mNetworkInfo.getType() != networkType) ||
+                    (mNetworkInfo.getState() != expectedState)) {
+                    Log.v(LOG_TAG, "network state for " + mNetworkInfo.getType() +
+                            "is: " + mNetworkInfo.getState());
+                    continue;
+                }
+                return true;
+            }
+        }
+    }
+
+    // Wait for Wifi state: WIFI_STATE_DISABLED, WIFI_STATE_DISABLING, WIFI_STATE_ENABLED,
+    //                      WIFI_STATE_ENALBING, WIFI_STATE_UNKNOWN
+    public boolean waitForWifiState(int expectedState, long timeout) {
+        long startTime = System.currentTimeMillis();
+        while (true) {
+            if ((System.currentTimeMillis() - startTime) > timeout) {
+                if (mWifiState != expectedState) {
+                    return false;
+                } else {
+                    return true;
+                }
+            }
+            Log.v(LOG_TAG, "Wait for wifi state to be: " + expectedState);
+            synchronized (wifiObject) {
+                try {
+                    wifiObject.wait(SHORT_TIMEOUT);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+                if (mWifiState != expectedState) {
+                    Log.v(LOG_TAG, "Wifi state is: " + mWifiNetworkInfo.getState());
+                    continue;
+                }
+                return true;
+            }
+        }
+    }
+
     // Return true if device is currently connected to mobile network
     public boolean isConnectedToMobile() {
         return (mNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE);
@@ -265,6 +352,22 @@
      * We don't verify whether the connection is successful or not, leave this to the test
      */
     public boolean connectToWifi(String knownSSID) {
+        WifiConfiguration config = new WifiConfiguration();
+        config.SSID = knownSSID;
+        config.allowedKeyManagement.set(KeyMgmt.NONE);
+        return connectToWifiWithConfiguration(config);
+    }
+
+    /**
+     * Connect to Wi-Fi with the given configuration. Note the SSID in the configuration
+     * is pure string, we need to convert it to quoted string.
+     * @param config
+     * @return
+     */
+    public boolean connectToWifiWithConfiguration(WifiConfiguration config) {
+        String ssid = config.SSID;
+        config.SSID = convertToQuotedString(ssid);
+
         //If Wifi is not enabled, enable it
         if (!mWifiManager.isWifiEnabled()) {
             Log.v(LOG_TAG, "Wifi is not enabled, enable it");
@@ -273,6 +376,7 @@
 
         List<ScanResult> netList = mWifiManager.getScanResults();
         if (netList == null) {
+            Log.v(LOG_TAG, "scan results are null");
             // if no scan results are available, start active scan
             mWifiManager.startScanActive();
             mScanResultIsAvailable = false;
@@ -299,17 +403,20 @@
         }
 
         netList = mWifiManager.getScanResults();
+
         for (int i = 0; i < netList.size(); i++) {
             ScanResult sr= netList.get(i);
-            if (sr.SSID.equals(knownSSID)) {
-                Log.v(LOG_TAG, "found " + knownSSID + " in the scan result list");
-                WifiConfiguration config = new WifiConfiguration();
-                config.SSID = convertToQuotedString(sr.SSID);
-                config.allowedKeyManagement.set(KeyMgmt.NONE);
+            if (sr.SSID.equals(ssid)) {
+                Log.v(LOG_TAG, "found " + ssid + " in the scan result list");
                 int networkId = mWifiManager.addNetwork(config);
                 // Connect to network by disabling others.
                 mWifiManager.enableNetwork(networkId, true);
                 mWifiManager.saveConfiguration();
+                List<WifiConfiguration> wifiNetworks = mWifiManager.getConfiguredNetworks();
+                for (WifiConfiguration netConfig : wifiNetworks) {
+                    Log.v(LOG_TAG, netConfig.toString());
+                }
+
                 mWifiManager.reconnect();
                 break;
            }
@@ -317,14 +424,14 @@
 
         List<WifiConfiguration> netConfList = mWifiManager.getConfiguredNetworks();
         if (netConfList.size() <= 0) {
-            Log.v(LOG_TAG, knownSSID + " is not available");
+            Log.v(LOG_TAG, ssid + " is not available");
             return false;
         }
         return true;
     }
 
     /*
-     * Disconnect from the current AP
+     * Disconnect from the current AP and remove configured networks.
      */
     public boolean disconnectAP() {
         if (mWifiManager.isWifiEnabled()) {
@@ -360,9 +467,9 @@
     }
 
     /**
-     * Disconnect from the current Wifi and clear the configuration list
+     * Remove configured networks and disable wifi
      */
-    public boolean clearWifi() {
+    public boolean removeConfiguredNetworksAndDisableWifi() {
             if (!disconnectAP()) {
                 return false;
             }
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java
index 592be92..3d4dc3d 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestRunner.java
@@ -21,6 +21,7 @@
 import android.test.InstrumentationTestSuite;
 import android.util.Log;
 import com.android.connectivitymanagertest.functional.ConnectivityManagerMobileTest;
+import com.android.connectivitymanagertest.functional.WifiConnectionTest;
 
 import junit.framework.TestSuite;
 
@@ -38,6 +39,7 @@
     public TestSuite getAllTests() {
         TestSuite suite = new InstrumentationTestSuite(this);
         suite.addTestSuite(ConnectivityManagerMobileTest.class);
+        suite.addTestSuite(WifiConnectionTest.class);
         return suite;
     }
 
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
index ad8d444..5959cf3 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
@@ -41,8 +41,6 @@
     extends ActivityInstrumentationTestCase2<ConnectivityManagerTestActivity> {
     private static final String LOG_TAG = "ConnectivityManagerMobileTest";
     private static final String PKG_NAME = "com.android.connectivitymanagertest";
-    private static final long STATE_TRANSITION_SHORT_TIMEOUT = 5 * 1000;
-    private static final long STATE_TRANSITION_LONG_TIMEOUT = 30 * 1000;
 
     private String TEST_ACCESS_POINT;
     private ConnectivityManagerTestActivity cmActivity;
@@ -64,9 +62,14 @@
         wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "CMWakeLock");
         wl.acquire();
         // Each test case will start with cellular connection
-        waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
-                STATE_TRANSITION_LONG_TIMEOUT);
-        verifyCellularConnection();
+        if (!cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT)) {
+            // Note: When the test fails in setUp(), tearDown is not called. In that case,
+            // the activity is destroyed which blocks the next test at "getActivity()".
+            // tearDown() is called hear to avoid that situation.
+            tearDown();
+            fail("Device is not connected to Mobile, setUp failed");
+        }
     }
 
     @Override
@@ -74,86 +77,26 @@
         cmActivity.finish();
         Log.v(LOG_TAG, "tear down ConnectivityManagerTestActivity");
         wl.release();
-        cmActivity.clearWifi();
+        cmActivity.removeConfiguredNetworksAndDisableWifi();
         super.tearDown();
     }
 
     // help function to verify 3G connection
     public void verifyCellularConnection() {
-        NetworkInfo extraNetInfo = cmActivity.mNetworkInfo;
+        NetworkInfo extraNetInfo = cmActivity.mCM.getActiveNetworkInfo();
         assertEquals("network type is not MOBILE", ConnectivityManager.TYPE_MOBILE,
-            extraNetInfo.getType());
+                extraNetInfo.getType());
         assertTrue("not connected to cellular network", extraNetInfo.isConnected());
         assertTrue("no data connection", cmActivity.mState.equals(State.CONNECTED));
     }
 
-    // Wait for network connectivity state: CONNECTING, CONNECTED, SUSPENDED,
-    //                                      DISCONNECTING, DISCONNECTED, UNKNOWN
-    private void waitForNetworkState(int networkType, State expectedState, long timeout) {
-        long startTime = System.currentTimeMillis();
-        while (true) {
-            if ((System.currentTimeMillis() - startTime) > timeout) {
-                if (cmActivity.mCM.getNetworkInfo(networkType).getState() != expectedState) {
-                    assertFalse("Wait for network state timeout", true);
-                } else {
-                    // the broadcast has been sent out. the state has been changed.
-                    return;
-                }
-            }
-            Log.v(LOG_TAG, "Wait for the connectivity state for network: " + networkType +
-                    " to be " + expectedState.toString());
-            synchronized (cmActivity.connectivityObject) {
-                try {
-                    cmActivity.connectivityObject.wait(STATE_TRANSITION_SHORT_TIMEOUT);
-                } catch (InterruptedException e) {
-                    e.printStackTrace();
-                }
-                if ((cmActivity.mNetworkInfo.getType() != networkType) ||
-                    (cmActivity.mNetworkInfo.getState() != expectedState)) {
-                    Log.v(LOG_TAG, "network state for " + cmActivity.mNetworkInfo.getType() +
-                            "is: " + cmActivity.mNetworkInfo.getState());
-                    continue;
-                }
-                break;
-            }
-        }
-    }
-
-    // Wait for Wifi state: WIFI_STATE_DISABLED, WIFI_STATE_DISABLING, WIFI_STATE_ENABLED,
-    //                      WIFI_STATE_ENALBING, WIFI_STATE_UNKNOWN
-    private void waitForWifiState(int expectedState, long timeout) {
-        long startTime = System.currentTimeMillis();
-        while (true) {
-            if ((System.currentTimeMillis() - startTime) > timeout) {
-                if (cmActivity.mWifiState != expectedState) {
-                    assertFalse("Wait for Wifi state timeout", true);
-                } else {
-                    return;
-                }
-            }
-            Log.v(LOG_TAG, "Wait for wifi state to be: " + expectedState);
-            synchronized (cmActivity.wifiObject) {
-                try {
-                    cmActivity.wifiObject.wait(5*1000);
-                } catch (InterruptedException e) {
-                    e.printStackTrace();
-                }
-                if (cmActivity.mWifiState != expectedState) {
-                    Log.v(LOG_TAG, "Wifi state is: " + cmActivity.mWifiNetworkInfo.getState());
-                    continue;
-                }
-                break;
-            }
-        }
-    }
-
     // Test case 1: Test enabling Wifi without associating with any AP
     @LargeTest
     public void test3GToWifiNotification() {
         // To avoid UNKNOWN state when device boots up
         cmActivity.enableWifi();
         try {
-            Thread.sleep(2 * STATE_TRANSITION_SHORT_TIMEOUT);
+            Thread.sleep(2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT);
         } catch (Exception e) {
             Log.v(LOG_TAG, "exception: " + e.toString());
         }
@@ -170,7 +113,7 @@
         // Eanble Wifi
         cmActivity.enableWifi();
         try {
-            Thread.sleep(2 * STATE_TRANSITION_SHORT_TIMEOUT);
+            Thread.sleep(2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT);
         } catch (Exception e) {
             Log.v(LOG_TAG, "exception: " + e.toString());
         }
@@ -208,12 +151,13 @@
         assertTrue("failed to connect to " + TEST_ACCESS_POINT,
                 cmActivity.connectToWifi(TEST_ACCESS_POINT));
 
-        waitForWifiState(WifiManager.WIFI_STATE_ENABLED, STATE_TRANSITION_LONG_TIMEOUT);
+        assertTrue(cmActivity.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT));
         Log.v(LOG_TAG, "wifi state is enabled");
-        waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                STATE_TRANSITION_LONG_TIMEOUT);
-        waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED,
-                STATE_TRANSITION_LONG_TIMEOUT);
+        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT));
+        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT));
 
         // validate states
         if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
@@ -237,12 +181,13 @@
         // Connect to TEST_ACCESS_POINT
         assertTrue("failed to connect to " + TEST_ACCESS_POINT,
                 cmActivity.connectToWifi(TEST_ACCESS_POINT));
-        waitForWifiState(WifiManager.WIFI_STATE_ENABLED, STATE_TRANSITION_LONG_TIMEOUT);
-        waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                STATE_TRANSITION_LONG_TIMEOUT);
+        assertTrue(cmActivity.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT));
+        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT));
 
         try {
-            Thread.sleep(STATE_TRANSITION_SHORT_TIMEOUT);
+            Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
         } catch (Exception e) {
             Log.v(LOG_TAG, "exception: " + e.toString());
         }
@@ -255,11 +200,12 @@
         }
 
         // Wait for the Wifi state to be DISABLED
-        waitForWifiState(WifiManager.WIFI_STATE_DISABLED, STATE_TRANSITION_LONG_TIMEOUT);
-        waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
-                STATE_TRANSITION_LONG_TIMEOUT);
-        waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
-                STATE_TRANSITION_LONG_TIMEOUT);
+        assertTrue(cmActivity.waitForWifiState(WifiManager.WIFI_STATE_DISABLED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT));
+        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT));
+        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT));
 
         //Prepare for connectivity state verification
         NetworkInfo networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
@@ -275,10 +221,10 @@
         cmActivity.enableWifi();
 
         // Wait for Wifi to be connected and mobile to be disconnected
-        waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                STATE_TRANSITION_LONG_TIMEOUT);
-        waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED,
-                STATE_TRANSITION_LONG_TIMEOUT);
+        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT));
+        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT));
 
         // validate wifi states
         if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
@@ -298,12 +244,12 @@
         assertTrue("failed to connect to " + TEST_ACCESS_POINT,
                    cmActivity.connectToWifi(TEST_ACCESS_POINT));
 
-        waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-            STATE_TRANSITION_LONG_TIMEOUT);
+        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+            ConnectivityManagerTestActivity.LONG_TIMEOUT));
 
         // Wait for a few seconds to avoid the state that both Mobile and Wifi is connected
         try {
-            Thread.sleep(STATE_TRANSITION_SHORT_TIMEOUT);
+            Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
         } catch (Exception e) {
             Log.v(LOG_TAG, "exception: " + e.toString());
         }
@@ -318,12 +264,12 @@
                 NetworkState.TO_DISCONNECTION, State.DISCONNECTED);
 
         // clear Wifi
-        cmActivity.clearWifi();
+        cmActivity.removeConfiguredNetworksAndDisableWifi();
 
-        waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
-                STATE_TRANSITION_LONG_TIMEOUT);
-        waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
-                STATE_TRANSITION_LONG_TIMEOUT);
+        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT));
+        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT));
 
         // validate states
         if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
@@ -357,7 +303,7 @@
         // Enable airplane mode
         cmActivity.setAirplaneMode(getInstrumentation().getContext(), true);
         try {
-            Thread.sleep(STATE_TRANSITION_SHORT_TIMEOUT);
+            Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
         } catch (Exception e) {
             Log.v(LOG_TAG, "exception: " + e.toString());
         }
@@ -389,8 +335,8 @@
         // disable airplane mode
         cmActivity.setAirplaneMode(getInstrumentation().getContext(), false);
 
-        waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
-                STATE_TRANSITION_LONG_TIMEOUT);
+        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT));
 
         // Validate the state transition
         if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
@@ -414,8 +360,8 @@
         // Eanble airplane mode
         cmActivity.setAirplaneMode(getInstrumentation().getContext(), true);
 
-        waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED,
-                STATE_TRANSITION_LONG_TIMEOUT);
+        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT));
 
         NetworkInfo networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
         cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
@@ -429,8 +375,8 @@
         // Connect to Wifi
         assertTrue("failed to connect to " + TEST_ACCESS_POINT,
                    cmActivity.connectToWifi(TEST_ACCESS_POINT));
-        waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                            STATE_TRANSITION_LONG_TIMEOUT);
+        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                            ConnectivityManagerTestActivity.LONG_TIMEOUT));
 
         // validate state and broadcast
         if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
@@ -457,11 +403,11 @@
         assertTrue("failed to connect to " + TEST_ACCESS_POINT,
                 cmActivity.connectToWifi(TEST_ACCESS_POINT));
 
-        waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                STATE_TRANSITION_LONG_TIMEOUT);
+        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT));
 
         try {
-            Thread.sleep(STATE_TRANSITION_SHORT_TIMEOUT);
+            Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
         } catch (Exception e) {
             Log.v(LOG_TAG, "exception: " + e.toString());
         }
@@ -469,11 +415,11 @@
         // Enable airplane mode without clearing Wifi
         cmActivity.setAirplaneMode(getInstrumentation().getContext(), true);
 
-        waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
-                STATE_TRANSITION_LONG_TIMEOUT);
+        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT));
 
         try {
-            Thread.sleep(STATE_TRANSITION_SHORT_TIMEOUT);
+            Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
         } catch (Exception e) {
             Log.v(LOG_TAG, "exception: " + e.toString());
         }
@@ -487,10 +433,10 @@
         // Disable airplane mode
         cmActivity.setAirplaneMode(getInstrumentation().getContext(), false);
 
-        waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                            STATE_TRANSITION_LONG_TIMEOUT);
-        waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED,
-                            STATE_TRANSITION_LONG_TIMEOUT);
+        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                            ConnectivityManagerTestActivity.LONG_TIMEOUT));
+        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED,
+                            ConnectivityManagerTestActivity.LONG_TIMEOUT));
 
         // validate the state transition
         if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
@@ -508,14 +454,15 @@
         //Connect to TEST_ACCESS_POINT
         assertTrue("failed to connect to " + TEST_ACCESS_POINT,
                    cmActivity.connectToWifi(TEST_ACCESS_POINT));
-        waitForWifiState(WifiManager.WIFI_STATE_ENABLED, STATE_TRANSITION_LONG_TIMEOUT);
-        waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-                            STATE_TRANSITION_LONG_TIMEOUT);
+        assertTrue(cmActivity.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT));
+        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                            ConnectivityManagerTestActivity.LONG_TIMEOUT));
         assertNotNull("Not associated with any AP",
                       cmActivity.mWifiManager.getConnectionInfo().getBSSID());
 
         try {
-            Thread.sleep(STATE_TRANSITION_SHORT_TIMEOUT);
+            Thread.sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT);
         } catch (Exception e) {
             Log.v(LOG_TAG, "exception: " + e.toString());
         }
@@ -527,13 +474,14 @@
         }
 
         // Verify the connectivity state for Wifi is DISCONNECTED
-        waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
-                STATE_TRANSITION_LONG_TIMEOUT);
+        assertTrue(cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT));
 
         if (!cmActivity.disableWifi()) {
             Log.v(LOG_TAG, "disable Wifi failed");
             return;
         }
-        waitForWifiState(WifiManager.WIFI_STATE_DISABLED, STATE_TRANSITION_LONG_TIMEOUT);
+        assertTrue(cmActivity.waitForWifiState(WifiManager.WIFI_STATE_DISABLED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT));
     }
 }
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
new file mode 100644
index 0000000..69eb5db
--- /dev/null
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2010, 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 com.android.connectivitymanagertest.functional;
+
+import com.android.connectivitymanagertest.ConnectivityManagerTestActivity;
+import com.android.connectivitymanagertest.NetworkState;
+
+import android.R;
+import android.app.Activity;
+import android.content.Intent;
+import android.content.Context;
+import android.content.res.Resources;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.State;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test Wi-Fi connection with different configuration
+ * To run this tests:
+ *     adb shell am instrument -e class
+ *          com.android.connectivitymanagertest.functional.WifiConnectionTest
+ *          -w com.android.connectivitymanagertest/.ConnectivityManagerTestRunner
+ */
+public class WifiConnectionTest
+    extends ActivityInstrumentationTestCase2<ConnectivityManagerTestActivity> {
+    private static final String TAG = "WifiConnectionTest";
+    private static final boolean DEBUG = true;
+    private static final String PKG_NAME = "com.android.connectivitymanagertests";
+    private List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
+    private ConnectivityManagerTestActivity mAct;
+
+    public WifiConnectionTest() {
+        super(PKG_NAME, ConnectivityManagerTestActivity.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mAct = getActivity();
+        networks = mAct.loadNetworkConfigurations();
+        if (DEBUG) {
+            printNetworkConfigurations();
+        }
+
+        // enable Wifi and verify wpa_supplicant is started
+        assertTrue("enable Wifi failed", mAct.enableWifi());
+        try {
+            Thread.sleep( 2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT);
+        } catch (Exception e) {
+            fail("interrupted while waiting for WPA_SUPPLICANT to start");
+        }
+        WifiInfo mConnection = mAct.mWifiManager.getConnectionInfo();
+        assertNotNull(mConnection);
+        assertTrue("wpa_supplicant is not started ", mAct.mWifiManager.pingSupplicant());
+    }
+
+    private void printNetworkConfigurations() {
+        Log.v(TAG, "==== print network configurations parsed from XML file ====");
+        Log.v(TAG, "number of access points: " + networks.size());
+        for (WifiConfiguration config : networks) {
+            Log.v(TAG, config.toString());
+        }
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        mAct.removeConfiguredNetworksAndDisableWifi();
+        super.tearDown();
+    }
+
+    /**
+     * Connect to the provided Wi-Fi network
+     * @param config is the network configuration
+     * @return true if the connection is successful.
+     */
+    private void connectToWifi(WifiConfiguration config) {
+        // step 1: connect to the test access point
+        assertTrue("failed to connect to " + config.SSID,
+                mAct.connectToWifiWithConfiguration(config));
+
+        // step 2: verify Wifi state and network state;
+        assertTrue(mAct.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
+                ConnectivityManagerTestActivity.SHORT_TIMEOUT));
+        assertTrue(mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI,
+                State.CONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT));
+
+        // step 3: verify the current connected network is the given SSID
+        if (DEBUG) {
+            Log.v(TAG, "config.SSID = " + config.SSID);
+            Log.v(TAG, "mAct.mWifiManager.getConnectionInfo.getSSID()" +
+                    mAct.mWifiManager.getConnectionInfo().getSSID());
+        }
+        assertTrue(config.SSID.contains(mAct.mWifiManager.getConnectionInfo().getSSID()));
+
+        // Maintain the connection for 50 seconds before switching
+        try {
+            Thread.sleep(50*1000);
+        } catch (Exception e) {
+            fail("interrupted while waiting for WPA_SUPPLICANT to start");
+        }
+    }
+
+    @LargeTest
+    public void testWifiConnections() {
+        for (int i = 0; i < networks.size(); i++) {
+            connectToWifi(networks.get(i));
+            mAct.removeConfiguredNetworksAndDisableWifi();
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java b/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
index f019599..43cf06a 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
@@ -110,6 +110,21 @@
         mTestUtils.disable(adapter);
     }
 
+    public void testAcceptPair() {
+        int iterations = BluetoothTestRunner.sPairIterations;
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        BluetoothDevice device = adapter.getRemoteDevice(BluetoothTestRunner.sPairAddress);
+        mTestUtils.enable(adapter);
+
+        for (int i = 0; i < iterations; i++) {
+            mTestUtils.writeOutput("acceptPair iteration " + (i + 1) + " of " + iterations);
+            mTestUtils.acceptPair(adapter, device, BluetoothTestRunner.sPairPasskey,
+                    BluetoothTestRunner.sPairPin);
+            mTestUtils.unpair(adapter, device);
+        }
+        mTestUtils.disable(adapter);
+    }
+
     public void testConnectA2dp() {
         int iterations = BluetoothTestRunner.sConnectA2dpIterations;
         if (iterations == 0) {
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
index 328891c..29dee34 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
@@ -137,7 +137,6 @@
 
         @Override
         public void onReceive(Context context, Intent intent) {
-            Log.i("BT", intent.toString());
             if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(intent.getAction())) {
                 setFiredFlag(DISCOVERY_STARTED_FLAG);
             } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(intent.getAction())) {
@@ -203,7 +202,7 @@
             if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(intent.getAction())) {
                 int varient = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, -1);
                 assertNotSame(-1, varient);
-                switch(varient) {
+                switch (varient) {
                     case BluetoothDevice.PAIRING_VARIANT_PIN:
                         mDevice.setPin(mPin);
                         break;
@@ -252,7 +251,7 @@
             mDevice = device;
             mProfile = profile;
 
-            switch(mProfile) {
+            switch (mProfile) {
                 case BluetoothProfile.A2DP:
                     mConnectionAction = BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED;
                     break;
@@ -384,11 +383,14 @@
                 mask = 0; // Don't check for received intents since we might have missed them.
                 break;
             case BluetoothAdapter.STATE_OFF:
-            case BluetoothAdapter.STATE_TURNING_OFF:
                 assertFalse(adapter.isEnabled());
                 start = System.currentTimeMillis();
                 assertTrue(adapter.enable());
                 break;
+            case BluetoothAdapter.STATE_TURNING_OFF:
+                start = System.currentTimeMillis();
+                assertTrue(adapter.enable());
+                break;
             default:
                 removeReceiver(receiver);
                 fail(String.format("enable() invalid state: state=%d", state));
@@ -410,7 +412,6 @@
                     return;
                 }
             } else {
-                assertFalse(adapter.isEnabled());
                 assertEquals(BluetoothAdapter.STATE_TURNING_ON, state);
             }
             sleep(POLL_TIME);
@@ -437,7 +438,6 @@
             case BluetoothAdapter.STATE_TURNING_ON:
                 assertFalse(adapter.isEnabled());
                 start = System.currentTimeMillis();
-                assertTrue(adapter.disable());
                 break;
             case BluetoothAdapter.STATE_ON:
                 assertTrue(adapter.isEnabled());
@@ -470,7 +470,6 @@
                     return;
                 }
             } else {
-                assertFalse(adapter.isEnabled());
                 assertEquals(BluetoothAdapter.STATE_TURNING_OFF, state);
             }
             sleep(POLL_TIME);
@@ -629,11 +628,22 @@
     }
 
     public void pair(BluetoothAdapter adapter, BluetoothDevice device, int passkey, byte[] pin) {
+        pairOrAcceptPair(adapter, device, passkey, pin, true);
+    }
+
+    public void acceptPair(BluetoothAdapter adapter, BluetoothDevice device, int passkey,
+            byte[] pin) {
+        pairOrAcceptPair(adapter, device, passkey, pin, false);
+    }
+
+    private void pairOrAcceptPair(BluetoothAdapter adapter, BluetoothDevice device, int passkey,
+            byte[] pin, boolean pair) {
         int mask = PairReceiver.STATE_BONDING_FLAG | PairReceiver.STATE_BONDED_FLAG;
         long start = -1;
+        String methodName = pair ? "pair()" : "acceptPair()";
 
         if (!adapter.isEnabled()) {
-            fail("pair() bluetooth not enabled");
+            fail(methodName + " bluetooth not enabled");
         }
 
         PairReceiver receiver = getPairReceiver(device, passkey, pin, mask);
@@ -643,7 +653,9 @@
             case BluetoothDevice.BOND_NONE:
                 assertFalse(adapter.getBondedDevices().contains(device));
                 start = System.currentTimeMillis();
-                assertTrue(device.createBond());
+                if (pair) {
+                    assertTrue(device.createBond());
+                }
                 break;
             case BluetoothDevice.BOND_BONDING:
                 mask = 0; // Don't check for received intents since we might have missed them.
@@ -653,7 +665,8 @@
                 return;
             default:
                 removeReceiver(receiver);
-                fail(String.format("pair() invalid state: device=%s, state=%d", device, state));
+                fail(String.format("%s invalid state: device=%s, state=%d", methodName, device,
+                        state));
         }
 
         long s = System.currentTimeMillis();
@@ -664,10 +677,10 @@
                 if ((receiver.getFiredFlags() & mask) == mask) {
                     long finish = receiver.getCompletedTime();
                     if (start != -1 && finish != -1) {
-                        writeOutput(String.format("pair() completed in %d ms: device=%s",
+                        writeOutput(String.format("%s completed in %d ms: device=%s", methodName,
                                 (finish - start), device));
                     } else {
-                        writeOutput(String.format("pair() completed: device=%s", device));
+                        writeOutput(String.format("%s completed: device=%s", methodName, device));
                     }
                     removeReceiver(receiver);
                     return;
@@ -678,9 +691,9 @@
 
         int firedFlags = receiver.getFiredFlags();
         removeReceiver(receiver);
-        fail(String.format("pair() timeout: device=%s, state=%d (expected %d), "
-                + "flags=0x%x (expected 0x%x)", device, state, BluetoothDevice.BOND_BONDED,
-                firedFlags, mask));
+        fail(String.format("%s timeout: device=%s, state=%d (expected %d), "
+                + "flags=0x%x (expected 0x%x)", methodName, device, state,
+                BluetoothDevice.BOND_BONDED, firedFlags, mask));
     }
 
     public void unpair(BluetoothAdapter adapter, BluetoothDevice device) {
@@ -788,7 +801,7 @@
                     long finish = receiver.getCompletedTime();
                     if (start != -1 && finish != -1) {
                         writeOutput(String.format("connectProfile() completed in %d ms: "
-                                +"device=%s, profile=%d", (finish - start), device, profile));
+                                + "device=%s, profile=%d", (finish - start), device, profile));
                     } else {
                         writeOutput(String.format("connectProfile() completed: device=%s, "
                                 + "profile=%d", device, profile));
@@ -857,7 +870,7 @@
                     long finish = receiver.getCompletedTime();
                     if (start != -1 && finish != -1) {
                         writeOutput(String.format("disconnectProfile() completed in %d ms: "
-                                +"device=%s, profile=%d", (finish - start), device, profile));
+                                + "device=%s, profile=%d", (finish - start), device, profile));
                     } else {
                         writeOutput(String.format("disconnectProfile() completed: device=%s, "
                                 + "profile=%d", device, profile));
@@ -934,14 +947,12 @@
         long s = System.currentTimeMillis();
         switch (profile) {
             case BluetoothProfile.A2DP:
-                while (mA2dp != null
-                        && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
+                while (mA2dp != null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
                     sleep(POLL_TIME);
                 }
                 return mA2dp;
             case BluetoothProfile.HEADSET:
-                while (mHeadset != null
-                        && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
+                while (mHeadset != null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
                     sleep(POLL_TIME);
                 }
                 return mHeadset;
diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/threshold.rs b/libs/rs/java/ImageProcessing/src/com/android/rs/image/threshold.rs
index 698540b..3e81115 100644
--- a/libs/rs/java/ImageProcessing/src/com/android/rs/image/threshold.rs
+++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/threshold.rs
@@ -64,7 +64,7 @@
 
 
 static void copyInput() {
-    rs_allocation ain = {0};
+    rs_allocation ain;
     rsSetObject(&ain,rsGetAllocation(InPixel));
     uint32_t dimx = rsAllocationGetDimX(ain);
     uint32_t dimy = rsAllocationGetDimY(ain);
@@ -73,7 +73,6 @@
             ScratchPixel1[x + y * dimx] = convert_float4(InPixel[x + y * dimx]);
         }
     }
-    rsClearObject(&ain);
 }
 
 void filter() {
diff --git a/libs/rs/java/Samples/src/com/android/samples/rslist.rs b/libs/rs/java/Samples/src/com/android/samples/rslist.rs
index f29276a..0baccb8 100644
--- a/libs/rs/java/Samples/src/com/android/samples/rslist.rs
+++ b/libs/rs/java/Samples/src/com/android/samples/rslist.rs
@@ -46,7 +46,7 @@
     rsgBindFont(gItalic);
     color(0.2, 0.2, 0.2, 0);
 
-    rs_allocation listAlloc = {0};
+    rs_allocation listAlloc;
     rsSetObject(&listAlloc, rsGetAllocation(gList));
     int allocSize = rsAllocationGetDimX(listAlloc);
 
@@ -67,7 +67,6 @@
         }
         currentYPos += itemHeight;
     }
-    rsClearObject(&listAlloc);
 
     return 10;
 }
diff --git a/libs/rs/java/tests/src/com/android/rs/test/rslist.rs b/libs/rs/java/tests/src/com/android/rs/test/rslist.rs
index d1fde57..f354a72 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/rslist.rs
+++ b/libs/rs/java/tests/src/com/android/rs/test/rslist.rs
@@ -47,7 +47,7 @@
     rsgBindFont(gFont);
     color(0.2, 0.2, 0.2, 0);
 
-    rs_allocation listAlloc = {0};
+    rs_allocation listAlloc;
     rsSetObject(&listAlloc, rsGetAllocation(gList));
     int allocSize = rsAllocationGetDimX(listAlloc);
 
@@ -103,7 +103,6 @@
         }
         currentYPos += itemHeight;
     }
-    rsClearObject(&listAlloc);
 
     return 10;
 }
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 7f4960f..69b872b 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -434,24 +434,23 @@
                 }
             }
 
-            mMimeType = null;
+            mMimeType = mimeType;
             mFileType = 0;
             mFileSize = fileSize;
 
             // try mimeType first, if it is specified
             if (mimeType != null) {
                 mFileType = MediaFile.getFileTypeForMimeType(mimeType);
-                if (mFileType != 0) {
-                    mMimeType = mimeType;
-                }
             }
 
             // if mimeType was not specified, compute file type based on file extension.
-            if (mMimeType == null) {
+            if (mFileType == 0) {
                 MediaFile.MediaFileType mediaFileType = MediaFile.getFileType(path);
                 if (mediaFileType != null) {
                     mFileType = mediaFileType.fileType;
-                    mMimeType = mediaFileType.mimeType;
+                    if (mMimeType == null) {
+                        mMimeType = mediaFileType.mimeType;
+                    }
                 }
             }
 
diff --git a/media/libstagefright/codecs/aacenc/AACEncoder.cpp b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
index df9f107..9524884 100644
--- a/media/libstagefright/codecs/aacenc/AACEncoder.cpp
+++ b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
@@ -36,6 +36,7 @@
       mStarted(false),
       mBufferGroup(NULL),
       mInputBuffer(NULL),
+      mInputFrame(NULL),
       mEncoderHandle(NULL),
       mApiHandle(NULL),
       mMemOperator(NULL) {
@@ -45,6 +46,7 @@
     CHECK(mApiHandle == NULL && mEncoderHandle == NULL);
     CHECK(mMeta->findInt32(kKeySampleRate, &mSampleRate));
     CHECK(mMeta->findInt32(kKeyChannelCount, &mChannels));
+    CHECK(mChannels <= 2 && mChannels >= 1);
     CHECK(mMeta->findInt32(kKeyBitRate, &mBitRate));
 
     mApiHandle = new VO_AUDIO_CODECAPI;
@@ -145,6 +147,10 @@
     mNumInputSamples = 0;
     mAnchorTimeUs = 0;
     mFrameCount = 0;
+
+    mInputFrame = new int16_t[mChannels * kNumSamplesPerFrame];
+    CHECK(mInputFrame != NULL);
+
     mSource->start(params);
 
     mStarted = true;
@@ -176,6 +182,10 @@
     mApiHandle = NULL;
 
     mStarted = false;
+    if (mInputFrame) {
+        delete[] mInputFrame;
+        mInputFrame = NULL;
+    }
 
     return OK;
 }
@@ -222,7 +232,8 @@
         buffer->meta_data()->setInt32(kKeyIsCodecConfig, false);
     }
 
-    while (mNumInputSamples < kNumSamplesPerFrame) {
+    const int32_t nSamples = mChannels * kNumSamplesPerFrame;
+    while (mNumInputSamples < nSamples) {
         if (mInputBuffer == NULL) {
             if (mSource->read(&mInputBuffer, options) != OK) {
                 if (mNumInputSamples == 0) {
@@ -231,7 +242,7 @@
                 }
                 memset(&mInputFrame[mNumInputSamples],
                        0,
-                       sizeof(int16_t) * (kNumSamplesPerFrame - mNumInputSamples));
+                       sizeof(int16_t) * (nSamples - mNumInputSamples));
                 mNumInputSamples = 0;
                 break;
             }
@@ -250,8 +261,7 @@
         } else {
             readFromSource = false;
         }
-        size_t copy =
-            (kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t);
+        size_t copy = (nSamples - mNumInputSamples) * sizeof(int16_t);
 
         if (copy > mInputBuffer->range_length()) {
             copy = mInputBuffer->range_length();
@@ -271,8 +281,8 @@
             mInputBuffer = NULL;
         }
         mNumInputSamples += copy / sizeof(int16_t);
-        if (mNumInputSamples >= kNumSamplesPerFrame) {
-            mNumInputSamples %= kNumSamplesPerFrame;
+        if (mNumInputSamples >= nSamples) {
+            mNumInputSamples %= nSamples;
             break;
         }
     }
@@ -280,7 +290,7 @@
     VO_CODECBUFFER inputData;
     memset(&inputData, 0, sizeof(inputData));
     inputData.Buffer = (unsigned char*) mInputFrame;
-    inputData.Length = kNumSamplesPerFrame * sizeof(int16_t);
+    inputData.Length = nSamples * sizeof(int16_t);
     CHECK(VO_ERR_NONE == mApiHandle->SetInputData(mEncoderHandle,&inputData));
 
     VO_CODECBUFFER outputData;
@@ -289,15 +299,21 @@
     memset(&outputInfo, 0, sizeof(outputInfo));
 
     VO_U32 ret = VO_ERR_NONE;
-    outputData.Buffer = outPtr;
-    outputData.Length = buffer->size();
-    ret = mApiHandle->GetOutputData(mEncoderHandle, &outputData, &outputInfo);
-    CHECK(ret == VO_ERR_NONE || ret == VO_ERR_INPUT_BUFFER_SMALL);
-    CHECK(outputData.Length != 0);
-    buffer->set_range(0, outputData.Length);
+    size_t nOutputBytes = 0;
+    do {
+        outputData.Buffer = outPtr;
+        outputData.Length = buffer->size() - nOutputBytes;
+        ret = mApiHandle->GetOutputData(mEncoderHandle, &outputData, &outputInfo);
+        if (ret == VO_ERR_NONE) {
+            outPtr += outputData.Length;
+            nOutputBytes += outputData.Length;
+        }
+    } while (ret != VO_ERR_INPUT_BUFFER_SMALL);
+    buffer->set_range(0, nOutputBytes);
 
     int64_t mediaTimeUs =
         ((mFrameCount - 1) * 1000000LL * kNumSamplesPerFrame) / mSampleRate;
+
     buffer->meta_data()->setInt64(kKeyTime, mAnchorTimeUs + mediaTimeUs);
     if (readFromSource && wallClockTimeUs != -1) {
         buffer->meta_data()->setInt64(kKeyDriftTime, mediaTimeUs - wallClockTimeUs);
diff --git a/media/libstagefright/httplive/LiveSource.cpp b/media/libstagefright/httplive/LiveSource.cpp
index 39e3e75..f9d27eb 100644
--- a/media/libstagefright/httplive/LiveSource.cpp
+++ b/media/libstagefright/httplive/LiveSource.cpp
@@ -278,7 +278,19 @@
         }
 
         if (mLastFetchTimeUs < 0) {
-            mPlaylistIndex = 0;
+            if (isSeekable()) {
+                mPlaylistIndex = 0;
+            } else {
+                // This is live streamed content, the first seqnum in the
+                // various bandwidth' streams may be slightly off, so don't
+                // start at the very first entry.
+                // With a segment duration of 6-10secs, this really only
+                // delays playback up to 30secs compared to real time.
+                mPlaylistIndex = 3;
+                if (mPlaylistIndex >= mPlaylist->size()) {
+                    mPlaylistIndex = mPlaylist->size() - 1;
+                }
+            }
         } else {
             if (nextSequenceNumber < mFirstItemSequenceNumber
                     || nextSequenceNumber
diff --git a/media/libstagefright/include/AACEncoder.h b/media/libstagefright/include/AACEncoder.h
index ecc533f..3d5fc60 100644
--- a/media/libstagefright/include/AACEncoder.h
+++ b/media/libstagefright/include/AACEncoder.h
@@ -60,7 +60,7 @@
             kNumSamplesPerFrame = 1024,
         };
 
-        int16_t           mInputFrame[kNumSamplesPerFrame];
+        int16_t           *mInputFrame;
 
         uint8_t           mAudioSpecificConfigData[2]; // auido specific data
         void             *mEncoderHandle;
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp
index d16476d..a40c0a3 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.cpp
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -22,13 +22,15 @@
 
 #include "mkvparser.hpp"
 
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
 #include <utils/String8.h>
 
 namespace android {
@@ -81,46 +83,6 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-#include <ctype.h>
-static void hexdump(const void *_data, size_t size) {
-    const uint8_t *data = (const uint8_t *)_data;
-    size_t offset = 0;
-    while (offset < size) {
-        printf("0x%04x  ", offset);
-
-        size_t n = size - offset;
-        if (n > 16) {
-            n = 16;
-        }
-
-        for (size_t i = 0; i < 16; ++i) {
-            if (i == 8) {
-                printf(" ");
-            }
-
-            if (offset + i < size) {
-                printf("%02x ", data[offset + i]);
-            } else {
-                printf("   ");
-            }
-        }
-
-        printf(" ");
-
-        for (size_t i = 0; i < n; ++i) {
-            if (isprint(data[offset + i])) {
-                printf("%c", data[offset + i]);
-            } else {
-                printf(".");
-            }
-        }
-
-        printf("\n");
-
-        offset += 16;
-    }
-}
-
 struct BlockIterator {
     BlockIterator(mkvparser::Segment *segment, unsigned long trackNum);
 
@@ -167,6 +129,7 @@
     size_t mTrackIndex;
     Type mType;
     BlockIterator mBlockIter;
+    size_t mNALSizeLen;  // for type AVC
 
     status_t advance();
 
@@ -180,13 +143,26 @@
       mTrackIndex(index),
       mType(OTHER),
       mBlockIter(mExtractor->mSegment,
-                 mExtractor->mTracks.itemAt(index).mTrackNum) {
+                 mExtractor->mTracks.itemAt(index).mTrackNum),
+      mNALSizeLen(0) {
+    sp<MetaData> meta = mExtractor->mTracks.itemAt(index).mMeta;
+
     const char *mime;
-    CHECK(mExtractor->mTracks.itemAt(index).mMeta->
-            findCString(kKeyMIMEType, &mime));
+    CHECK(meta->findCString(kKeyMIMEType, &mime));
 
     if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
         mType = AVC;
+
+        uint32_t dummy;
+        const uint8_t *avcc;
+        size_t avccSize;
+        CHECK(meta->findData(
+                    kKeyAVCC, &dummy, (const void **)&avcc, &avccSize));
+
+        CHECK_GE(avccSize, 5u);
+
+        mNALSizeLen = 1 + (avcc[4] & 3);
+        LOGV("mNALSizeLen = %d", mNALSizeLen);
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
         mType = AAC;
     }
@@ -276,6 +252,10 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
+static unsigned U24_AT(const uint8_t *ptr) {
+    return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
+}
+
 status_t MatroskaSource::read(
         MediaBuffer **out, const ReadOptions *options) {
     *out = NULL;
@@ -286,6 +266,7 @@
         mBlockIter.seek(seekTimeUs);
     }
 
+again:
     if (mBlockIter.eos()) {
         return ERROR_END_OF_STREAM;
     }
@@ -294,38 +275,70 @@
     size_t size = block->GetSize();
     int64_t timeUs = mBlockIter.blockTimeUs();
 
-    MediaBuffer *buffer = new MediaBuffer(size + 2);
+    // In the case of AVC content, each NAL unit is prefixed by
+    // mNALSizeLen bytes of length. We want to prefix the data with
+    // a four-byte 0x00000001 startcode instead of the length prefix.
+    // mNALSizeLen ranges from 1 through 4 bytes, so add an extra
+    // 3 bytes of padding to the buffer start.
+    static const size_t kPadding = 3;
+
+    MediaBuffer *buffer = new MediaBuffer(size + kPadding);
     buffer->meta_data()->setInt64(kKeyTime, timeUs);
     buffer->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey());
 
     long res = block->Read(
-            mExtractor->mReader, (unsigned char *)buffer->data() + 2);
+            mExtractor->mReader, (unsigned char *)buffer->data() + kPadding);
 
     if (res != 0) {
         return ERROR_END_OF_STREAM;
     }
 
-    buffer->set_range(2, size);
+    buffer->set_range(kPadding, size);
 
     if (mType == AVC) {
-        CHECK(size >= 2);
+        CHECK_GE(size, mNALSizeLen);
 
         uint8_t *data = (uint8_t *)buffer->data();
 
-        unsigned NALsize = data[2] << 8 | data[3];
-        CHECK_EQ(size, NALsize + 2);
+        size_t NALsize;
+        switch (mNALSizeLen) {
+            case 1: NALsize = data[kPadding]; break;
+            case 2: NALsize = U16_AT(&data[kPadding]); break;
+            case 3: NALsize = U24_AT(&data[kPadding]); break;
+            case 4: NALsize = U32_AT(&data[kPadding]); break;
+            default:
+                TRESPASS();
+        }
 
-        memcpy(data, "\x00\x00\x00\x01", 4);
-        buffer->set_range(0, size + 2);
+        CHECK_GE(size, NALsize + mNALSizeLen);
+        if (size > NALsize + mNALSizeLen) {
+            LOGW("discarding %d bytes of data.", size - NALsize - mNALSizeLen);
+        }
+
+        // actual data starts at &data[kPadding + mNALSizeLen]
+
+        memcpy(&data[mNALSizeLen - 1], "\x00\x00\x00\x01", 4);
+        buffer->set_range(mNALSizeLen - 1, NALsize + 4);
     } else if (mType == AAC) {
         // There's strange junk at the beginning...
 
-        const uint8_t *data = (const uint8_t *)buffer->data() + 2;
+        const uint8_t *data = (const uint8_t *)buffer->data() + kPadding;
+
+        // hexdump(data, size);
+
         size_t offset = 0;
         while (offset < size && data[offset] != 0x21) {
             ++offset;
         }
-        buffer->set_range(2 + offset, size - offset);
+
+        if (size == offset) {
+            buffer->release();
+
+            mBlockIter.advance();
+            goto again;
+        }
+
+        buffer->set_range(kPadding + offset, size - offset);
     }
 
     *out = buffer;
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_quicksettings.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_quicksettings.png
new file mode 100644
index 0000000..4434b5c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_quicksettings.png
Binary files differ
diff --git a/packages/SystemUI/res/layout-xlarge/sysbar_panel_notification_peek.xml b/packages/SystemUI/res/layout-xlarge/sysbar_panel_notification_peek.xml
index a7c91f5..02f9a90 100644
--- a/packages/SystemUI/res/layout-xlarge/sysbar_panel_notification_peek.xml
+++ b/packages/SystemUI/res/layout-xlarge/sysbar_panel_notification_peek.xml
@@ -19,7 +19,7 @@
 -->
 
 <!--    android:background="@drawable/status_bar_closed_default_background" -->
-<com.android.systemui.statusbar.tablet.NotificationPanel
+<com.android.systemui.statusbar.tablet.NotificationPeekPanel
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_height="wrap_content"
     android:layout_width="match_parent"
@@ -40,4 +40,4 @@
         android:descendantFocusability="afterDescendants"
         >
     </FrameLayout>
-</com.android.systemui.statusbar.tablet.NotificationPanel>
+</com.android.systemui.statusbar.tablet.NotificationPeekPanel>
diff --git a/packages/SystemUI/res/layout-xlarge/sysbar_panel_notifications.xml b/packages/SystemUI/res/layout-xlarge/sysbar_panel_notifications.xml
index 6a8ae40..884a473 100644
--- a/packages/SystemUI/res/layout-xlarge/sysbar_panel_notifications.xml
+++ b/packages/SystemUI/res/layout-xlarge/sysbar_panel_notifications.xml
@@ -44,13 +44,27 @@
         android:gravity="right"
         />
 
-    <Button
+    <ImageView
         android:id="@+id/settings_button"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_below="@id/date"
         android:layout_alignParentRight="true"
-        android:text="@string/system_panel_settings_button"
+        android:paddingRight="10dp"
+        android:src="@drawable/ic_sysbar_quicksettings"
+        android:baseline="17dp"
+        />
+
+    <ImageView
+        android:id="@+id/notification_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignBaseline="@id/settings_button"
+        android:layout_alignParentRight="true"
+        android:paddingRight="10dp"
+        android:visibility="invisible"
+        android:src="@drawable/status_bar_veto"
+        android:baseline="17dp"
         />
 
     <ImageView
@@ -93,6 +107,13 @@
         android:text="@string/system_panel_settings_button"
         />
 
+    <FrameLayout
+        android:id="@+id/settings_frame"
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:layout_below="@id/settings_button"
+        />
+
     <ScrollView
         android:id="@+id/notificationScroller"
         android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/layout-xlarge/sysbar_panel_settings.xml b/packages/SystemUI/res/layout-xlarge/sysbar_panel_settings.xml
new file mode 100644
index 0000000..c6ddfed
--- /dev/null
+++ b/packages/SystemUI/res/layout-xlarge/sysbar_panel_settings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2010 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.
+-->
+
+<com.android.systemui.statusbar.tablet.SettingsPanel
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="200dip"
+    >
+</com.android.systemui.statusbar.tablet.SettingsPanel>
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index f1b76f6..4ff2429 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -321,7 +321,9 @@
                 mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
             }
         } else {
-            if (isCdma()) {
+            if (mSignalStrength == null) {
+                mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
+            } else if (isCdma()) {
                 // If 3G(EV) and 1x network are available than 3G should be
                 // displayed, displayed RSSI should be from the EV side.
                 // If a voice call is made then RSSI should switch to 1x.
@@ -497,7 +499,8 @@
             if (mWifiConnected && !wasConnected) {
                 WifiInfo info = mWifiManager.getConnectionInfo();
                 if (info != null) {
-                    mWifiLevel = WifiManager.calculateSignalLevel(info.getRssi(), 101);
+                    mWifiLevel = WifiManager.calculateSignalLevel(info.getRssi(),
+                            WifiIcons.WIFI_LEVEL_COUNT);
                     mWifiSsid = huntForSsid(info);
                 } else {
                     mWifiLevel = 0;
@@ -511,7 +514,7 @@
         } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
             if (mWifiConnected) {
                 final int newRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
-                mWifiLevel = WifiManager.calculateSignalLevel(newRssi, 101);
+                mWifiLevel = WifiManager.calculateSignalLevel(newRssi, WifiIcons.WIFI_LEVEL_COUNT);
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
index d218ebf..0787289 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
@@ -29,4 +29,6 @@
               R.drawable.stat_sys_wifi_signal_3_fully,
               R.drawable.stat_sys_wifi_signal_4_fully }
         };
+
+    static final int WIFI_LEVEL_COUNT = WIFI_SIGNAL_STRENGTH[0].length;
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
index 1a08f22..ce81fdc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
@@ -18,13 +18,25 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
+import android.util.Slog;
 import android.widget.ImageView;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
+import android.view.View;
+import android.widget.FrameLayout;
 
 import com.android.systemui.R;
 
-public class NotificationPanel extends RelativeLayout implements StatusBarPanel {
+public class NotificationPanel extends RelativeLayout implements StatusBarPanel,
+        View.OnClickListener {
+    static final String TAG = "NotificationPanel";
+
+    View mSettingsButton;
+    View mNotificationButton;
+    View mNotificationScroller;
+    FrameLayout mSettingsFrame;
+    View mSettingsPanel;
+
     public NotificationPanel(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
     }
@@ -33,6 +45,51 @@
         super(context, attrs, defStyle);
     }
 
+    @Override
+    public void onFinishInflate() {
+        super.onFinishInflate();
+
+        mSettingsButton = (ImageView)findViewById(R.id.settings_button);
+        mSettingsButton.setOnClickListener(this);
+        mNotificationButton = (ImageView)findViewById(R.id.notification_button);
+        mNotificationButton.setOnClickListener(this);
+
+        mNotificationScroller = findViewById(R.id.notificationScroller);
+        mSettingsFrame = (FrameLayout)findViewById(R.id.settings_frame);
+    }
+
+    @Override
+    public void onVisibilityChanged(View v, int vis) {
+        super.onVisibilityChanged(v, vis);
+        // when we hide, put back the notifications
+        if (!isShown()) {
+            switchToNotificationMode();
+        }
+    }
+
+    public void onClick(View v) {
+        if (v == mSettingsButton) {
+            switchToSettingsMode();
+        } else if (v == mNotificationButton) {
+            switchToNotificationMode();
+        }
+    }
+
+    public void switchToSettingsMode() {
+        removeSettingsPanel();
+        addSettingsPanel();
+        mSettingsButton.setVisibility(View.INVISIBLE);
+        mNotificationScroller.setVisibility(View.GONE);
+        mNotificationButton.setVisibility(View.VISIBLE);
+    }
+
+    public void switchToNotificationMode() {
+        removeSettingsPanel();
+        mSettingsButton.setVisibility(View.VISIBLE);
+        mNotificationScroller.setVisibility(View.VISIBLE);
+        mNotificationButton.setVisibility(View.INVISIBLE);
+    }
+
     public boolean isInContentArea(int x, int y) {
         final int l = getPaddingLeft();
         final int r = getWidth() - getPaddingRight();
@@ -40,5 +97,16 @@
         final int b = getHeight() - getPaddingBottom();
         return x >= l && x < r && y >= t && y < b;
     }
+
+    void removeSettingsPanel() {
+        if (mSettingsPanel != null) {
+            mSettingsFrame.removeViewAt(0);
+            mSettingsPanel = null;
+        }
+    }
+
+    void addSettingsPanel() {
+        mSettingsPanel = View.inflate(getContext(), R.layout.sysbar_panel_settings, mSettingsFrame);
+    }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java
new file mode 100644
index 0000000..744f667
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2010 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 com.android.systemui.statusbar.tablet;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.RelativeLayout;
+
+import com.android.systemui.R;
+
+public class NotificationPeekPanel extends RelativeLayout implements StatusBarPanel {
+    public NotificationPeekPanel(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public NotificationPeekPanel(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    public boolean isInContentArea(int x, int y) {
+        final int l = getPaddingLeft();
+        final int r = getWidth() - getPaddingRight();
+        final int t = getPaddingTop();
+        final int b = getHeight() - getPaddingBottom();
+        return x >= l && x < r && y >= t && y < b;
+    }
+
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsPanel.java
new file mode 100644
index 0000000..9013f5c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsPanel.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2010 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 com.android.systemui.statusbar.tablet;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Slog;
+import android.widget.LinearLayout;
+import android.view.View;
+
+import com.android.systemui.R;
+
+public class SettingsPanel extends LinearLayout {
+    static final String TAG = "SettingsPanel";
+
+    public SettingsPanel(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public SettingsPanel(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 2efdf96..983215e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -99,7 +99,7 @@
     InputMethodButton mInputMethodButton;
 
     NotificationPanel mNotificationPanel;
-    NotificationPanel mNotificationPeekWindow;
+    NotificationPeekPanel mNotificationPeekWindow;
     ViewGroup mNotificationPeekRow;
     int mNotificationPeekIndex;
     LayoutTransition mNotificationPeekScrubLeft, mNotificationPeekScrubRight;
@@ -166,7 +166,7 @@
         WindowManagerImpl.getDefault().addView(mNotificationPanel, lp);
 
         // Notification preview window
-        mNotificationPeekWindow = (NotificationPanel) View.inflate(context,
+        mNotificationPeekWindow = (NotificationPeekPanel) View.inflate(context,
                 R.layout.sysbar_panel_notification_peek, null);
         mNotificationPeekRow = (ViewGroup) mNotificationPeekWindow.findViewById(R.id.content);
         mNotificationPeekWindow.setVisibility(View.GONE);
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index e99b74f..18815f5 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -411,6 +411,8 @@
     public final void openPanel(int featureId, KeyEvent event) {
         if (featureId == FEATURE_OPTIONS_PANEL && mActionBar != null &&
                 mActionBar.isOverflowReserved()) {
+            // Invalidate the options menu, we want a prepare event that the app can respond to.
+            invalidatePanelMenu(FEATURE_OPTIONS_PANEL);
             mActionBar.showOverflowMenu();
         } else {
             openPanel(getPanelState(featureId, true), event);
@@ -1830,7 +1832,12 @@
             }
 
             final ActionMode.Callback wrappedCallback = new ActionModeCallbackWrapper(callback);
-            ActionMode mode = getCallback().onStartActionMode(wrappedCallback);
+            ActionMode mode = null;
+            try {
+                mode = getCallback().onWindowStartingActionMode(wrappedCallback);
+            } catch (AbstractMethodError ame) {
+                // Older apps might not implement this callback method.
+            }
             if (mode != null) {
                 mActionMode = mode;
             } else {
@@ -1874,6 +1881,13 @@
                     }
                 }
             }
+            if (mActionMode != null) {
+                try {
+                    getCallback().onActionModeStarted(mActionMode);
+                } catch (AbstractMethodError ame) {
+                    // Older apps might not implement this callback method.
+                }
+            }
             return mActionMode;
         }
 
@@ -2089,6 +2103,11 @@
                 if (mActionModeView != null) {
                     mActionModeView.removeAllViews();
                 }
+                try {
+                    getCallback().onActionModeFinished(mActionMode);
+                } catch (AbstractMethodError ame) {
+                    // Older apps might not implement this callback method.
+                }
                 mActionMode = null;
             }
         }