Merge "Remove notifications when an app is disabled."
diff --git a/api/current.txt b/api/current.txt
index 035da89..a70e8a2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -14095,6 +14095,7 @@
     method public static long getNativeHeapAllocatedSize();
     method public static long getNativeHeapFreeSize();
     method public static long getNativeHeapSize();
+    method public static long getPss();
     method public static int getThreadAllocCount();
     method public static int getThreadAllocSize();
     method public static deprecated int getThreadExternalAllocCount();
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index b7cd829..a73e10a 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1523,6 +1523,15 @@
             return true;
         }
 
+        case GET_PROCESS_PSS_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            int[] pids = data.createIntArray();
+            long[] pss = getProcessPss(pids);
+            reply.writeNoException();
+            reply.writeLongArray(pss);
+            return true;
+        }
+
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -3432,5 +3441,18 @@
         reply.recycle();
     }
 
+    public long[] getProcessPss(int[] pids) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeIntArray(pids);
+        mRemote.transact(GET_PROCESS_PSS_TRANSACTION, data, reply, 0);
+        reply.readException();
+        long[] res = reply.createLongArray();
+        data.recycle();
+        reply.recycle();
+        return res;
+    }
+
     private IBinder mRemote;
 }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index c566104..d5f630a 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -729,17 +729,19 @@
         }
 
         @Override
-        public Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, String[] args) {
+        public Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, boolean checkin,
+                boolean all, String[] args) {
             FileOutputStream fout = new FileOutputStream(fd);
             PrintWriter pw = new PrintWriter(fout);
             try {
-                return dumpMemInfo(pw, args);
+                return dumpMemInfo(pw, checkin, all, args);
             } finally {
                 pw.flush();
             }
         }
 
-        private Debug.MemoryInfo dumpMemInfo(PrintWriter pw, String[] args) {
+        private Debug.MemoryInfo dumpMemInfo(PrintWriter pw, boolean checkin, boolean all,
+                String[] args) {
             long nativeMax = Debug.getNativeHeapSize() / 1024;
             long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
             long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
@@ -747,6 +749,10 @@
             Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
             Debug.getMemoryInfo(memInfo);
 
+            if (!all) {
+                return memInfo;
+            }
+
             Runtime runtime = Runtime.getRuntime();
 
             long dalvikMax = runtime.totalMemory() / 1024;
@@ -765,16 +771,8 @@
             long sqliteAllocated = SQLiteDebug.getHeapAllocatedSize() / 1024;
             SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo();
 
-            // Check to see if we were called by checkin server. If so, print terse format.
-            boolean doCheckinFormat = false;
-            if (args != null) {
-                for (String arg : args) {
-                    if ("-c".equals(arg)) doCheckinFormat = true;
-                }
-            }
-
             // For checkin, we print one long comma-separated list of values
-            if (doCheckinFormat) {
+            if (checkin) {
                 // NOTE: if you change anything significant below, also consider changing
                 // ACTIVITY_THREAD_CHECKIN_VERSION.
                 String processName = (mBoundApplication != null)
@@ -841,13 +839,17 @@
                 pw.print(sqliteAllocated); pw.print(',');
                 pw.print(stats.memoryUsed / 1024); pw.print(',');
                 pw.print(stats.pageCacheOverflo / 1024); pw.print(',');
-                pw.print(stats.largestMemAlloc / 1024); pw.print(',');
+                pw.print(stats.largestMemAlloc / 1024);
                 for (int i = 0; i < stats.dbStats.size(); i++) {
                     DbStats dbStats = stats.dbStats.get(i);
-                    printRow(pw, DB_INFO_FORMAT, dbStats.pageSize, dbStats.dbSize,
-                            dbStats.lookaside, dbStats.cache, dbStats.dbName);
-                    pw.print(',');
+                    pw.print(','); pw.print(dbStats.dbName);
+                    pw.print(','); pw.print(dbStats.pageSize);
+                    pw.print(','); pw.print(dbStats.dbSize);
+                    pw.print(','); pw.print(dbStats.lookaside);
+                    pw.print(','); pw.print(dbStats.cache);
+                    pw.print(','); pw.print(dbStats.cache);
                 }
+                pw.println();
 
                 return memInfo;
             }
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 9a5b527..bea057e 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -491,11 +491,13 @@
         {
             data.enforceInterface(IApplicationThread.descriptor);
             ParcelFileDescriptor fd = data.readFileDescriptor();
+            boolean checkin = data.readInt() != 0;
+            boolean all = data.readInt() != 0;
             String[] args = data.readStringArray();
             Debug.MemoryInfo mi = null;
             if (fd != null) {
                 try {
-                    mi = dumpMemInfo(fd.getFileDescriptor(), args);
+                    mi = dumpMemInfo(fd.getFileDescriptor(), checkin, all, args);
                 } finally {
                     try {
                         fd.close();
@@ -1049,11 +1051,14 @@
                 IBinder.FLAG_ONEWAY);
     }
 
-    public Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, String[] args) throws RemoteException {
+    public Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, boolean checkin, boolean all,
+            String[] args) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeFileDescriptor(fd);
+        data.writeInt(checkin ? 1 : 0);
+        data.writeInt(all ? 1 : 0);
         data.writeStringArray(args);
         mRemote.transact(DUMP_MEM_INFO_TRANSACTION, data, reply, 0);
         reply.readException();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 64d77e8..b1b0583 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -364,7 +364,9 @@
     public boolean isIntentSenderTargetedToPackage(IIntentSender sender) throws RemoteException;
 
     public void updatePersistentConfiguration(Configuration values) throws RemoteException;
-    
+
+    public long[] getProcessPss(int[] pids) throws RemoteException;
+
     /*
      * Private non-Binder interfaces
      */
@@ -593,4 +595,5 @@
     int UNREGISTER_PROCESS_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+133;
     int IS_INTENT_SENDER_TARGETED_TO_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+134;
     int UPDATE_PERSISTENT_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+135;
+    int GET_PROCESS_PSS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+136;
 }
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index d0607d0..3a8eb28 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -120,7 +120,8 @@
     void setCoreSettings(Bundle coreSettings) throws RemoteException;
     void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) throws RemoteException;
     void scheduleTrimMemory(int level) throws RemoteException;
-    Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, String[] args) throws RemoteException;
+    Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, boolean checkin, boolean all,
+            String[] args) throws RemoteException;
     void dumpGfxInfo(FileDescriptor fd, String[] args) throws RemoteException;
 
     String descriptor = "android.app.IApplicationThread";
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index da2afb6..20a731e 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -818,6 +818,18 @@
     public static native void getMemoryInfo(int pid, MemoryInfo memoryInfo);
 
     /**
+     * Retrieves the PSS memory used by the process as given by the
+     * smaps.
+     */
+    public static native long getPss();
+
+    /**
+     * Retrieves the PSS memory used by the process as given by the
+     * smaps. @hide
+     */
+    public static native long getPss(int pid);
+
+    /**
      * Establish an object allocation limit in the current thread.
      * This feature was never enabled in release builds.  The
      * allocation limits feature was removed in Honeycomb.  This
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 9a4e0fc..1ecdfce 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3042,7 +3042,7 @@
 
         /**
          * Boolean to determine whether to notify on disabling a network.  Secure setting used
-         * to notify user only once.  This setting is not monitored continuously.
+         * to notify user only once.
          * @hide
          */
         public static final String WIFI_WATCHDOG_SHOW_DISABLED_NETWORK_POPUP =
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 3a3f07e..85fac5f 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -279,6 +279,39 @@
     android_os_Debug_getDirtyPagesPid(env, clazz, getpid(), object);
 }
 
+static jlong android_os_Debug_getPssPid(JNIEnv *env, jobject clazz, jint pid)
+{
+    char line[1024];
+    jlong pss = 0;
+    unsigned temp;
+
+    char tmp[128];
+    FILE *fp;
+
+    sprintf(tmp, "/proc/%d/smaps", pid);
+    fp = fopen(tmp, "r");
+    if (fp == 0) return 0;
+
+    while (true) {
+        if (fgets(line, 1024, fp) == 0) {
+            break;
+        }
+
+        if (sscanf(line, "Pss: %d kB", &temp) == 1) {
+            pss += temp;
+        }
+    }
+
+    fclose(fp);
+
+    return pss;
+}
+
+static jlong android_os_Debug_getPss(JNIEnv *env, jobject clazz)
+{
+    return android_os_Debug_getPssPid(env, clazz, getpid());
+}
+
 static jint read_binder_stat(const char* stat)
 {
     FILE* fp = fopen(BINDER_STATS, "r");
@@ -520,6 +553,10 @@
             (void*) android_os_Debug_getDirtyPages },
     { "getMemoryInfo",          "(ILandroid/os/Debug$MemoryInfo;)V",
             (void*) android_os_Debug_getDirtyPagesPid },
+    { "getPss",                 "()J",
+            (void*) android_os_Debug_getPss },
+    { "getPss",                 "(I)J",
+            (void*) android_os_Debug_getPssPid },
     { "dumpNativeHeap",         "(Ljava/io/FileDescriptor;)V",
             (void*) android_os_Debug_dumpNativeHeap },
     { "getBinderSentTransactions", "()I",
diff --git a/core/res/res/drawable-hdpi/textfield_search_default_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_search_default_holo_dark.9.png
index 62e3274..288b809 100644
--- a/core/res/res/drawable-hdpi/textfield_search_default_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_default_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_search_default_holo_light.9.png
index b7512fa..7866e06 100644
--- a/core/res/res/drawable-hdpi/textfield_search_default_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_right_default_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_search_right_default_holo_dark.9.png
index bfc6f83..699552d 100644
--- a/core/res/res/drawable-hdpi/textfield_search_right_default_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_right_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_right_default_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_search_right_default_holo_light.9.png
index 708ba90..543afa2 100644
--- a/core/res/res/drawable-hdpi/textfield_search_right_default_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_right_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_dark.9.png
index 0da1e9c..e1a5e70 100644
--- a/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_light.9.png
index 2e93557..e79e95b 100644
--- a/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_selected_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_search_selected_holo_dark.9.png
index 7aeaad6..8a5d810 100644
--- a/core/res/res/drawable-hdpi/textfield_search_selected_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_selected_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_search_selected_holo_light.9.png
index cf46f32..177b631 100644
--- a/core/res/res/drawable-hdpi/textfield_search_selected_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png
index 62e3274..faaa6c2 100644
--- a/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png
index b7512fa..ec44405 100644
--- a/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_right_default_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_search_right_default_holo_dark.9.png
index bfc6f83..1cc76a3 100644
--- a/core/res/res/drawable-mdpi/textfield_search_right_default_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_right_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_right_default_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_search_right_default_holo_light.9.png
index 708ba90..2593760 100644
--- a/core/res/res/drawable-mdpi/textfield_search_right_default_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_right_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_dark.9.png
index 0da1e9c..8688d6a 100644
--- a/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_light.9.png
index 2e93557..3f4c282 100644
--- a/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_selected_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_search_selected_holo_dark.9.png
index 7aeaad6..8692528 100644
--- a/core/res/res/drawable-mdpi/textfield_search_selected_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_selected_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_search_selected_holo_light.9.png
index cf46f32..849af73 100644
--- a/core/res/res/drawable-mdpi/textfield_search_selected_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_default_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_search_default_holo_dark.9.png
new file mode 100644
index 0000000..1a1a9c4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/textfield_search_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_default_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_search_default_holo_light.9.png
new file mode 100644
index 0000000..462cea6
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/textfield_search_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_dark.9.png
new file mode 100644
index 0000000..3e178b2
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_light.9.png
new file mode 100644
index 0000000..4c34b93
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_dark.9.png
new file mode 100644
index 0000000..cf1b3ca
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_light.9.png
new file mode 100644
index 0000000..0ee383b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_selected_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_search_selected_holo_dark.9.png
new file mode 100644
index 0000000..42c019e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/textfield_search_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_selected_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_search_selected_holo_light.9.png
new file mode 100644
index 0000000..63efe71
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/textfield_search_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index afd8908..aa4387e5 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2583,10 +2583,10 @@
         <item quantity="other">Open Wi-Fi networks available</item>
     </plurals>
 
-     <!-- A notification is shown the first time a wireless network is disabled due to bad connectivity.  This is the notification's title / ticker. -->
-    <string name="wifi_watchdog_network_disabled">A Wi-Fi network was disabled</string>
-    <!--  A notification is shown the first time a wireless network is disabled due to bad connectivity.  This is the notification's message which leads to the settings pane -->
-    <string name="wifi_watchdog_network_disabled_detailed">A Wi-Fi network was temporarily disabled due to bad connectivity.</string>
+     <!-- A notification is shown when a user's selected SSID is later disabled due to connectivity problems.  This is the notification's title / ticker. -->
+     <string name="wifi_watchdog_network_disabled">Couldn\'t connect to Wi-Fi</string>
+     <!-- A notification is shown when a user's selected SSID is later disabled due to connectivity problems.  This is a partial string of the message, which will also include the (possibly truncated) hotspot name. -->
+    <string name="wifi_watchdog_network_disabled_detailed"> has a poor internet connection.</string>
 
     <!-- Do not translate. Default access point SSID used for tethering -->
     <string name="wifi_tether_configure_ssid_default" translatable="false">AndroidAP</string>
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 8339e4b..02017a1 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -307,7 +307,7 @@
     private Uri mThumbsUri;
     private Uri mPlaylistsUri;
     private Uri mFilesUri;
-    private boolean mProcessPlaylists;
+    private boolean mProcessPlaylists, mProcessGenres;
     private int mMtpObjectHandle;
 
     private final String mExternalStoragePath;
@@ -612,7 +612,8 @@
                 mAlbum = value.trim();
             } else if (name.equalsIgnoreCase("composer") || name.startsWith("composer;")) {
                 mComposer = value.trim();
-            } else if (name.equalsIgnoreCase("genre") || name.startsWith("genre;")) {
+            } else if (mProcessGenres &&
+                    (name.equalsIgnoreCase("genre") || name.startsWith("genre;"))) {
                 mGenre = getGenreName(value);
             } else if (name.equalsIgnoreCase("year") || name.startsWith("year;")) {
                 mYear = parseSubstring(value, 0, 0);
@@ -1151,6 +1152,7 @@
         if (!volumeName.equals("internal")) {
             // we only support playlists on external media
             mProcessPlaylists = true;
+            mProcessGenres = true;
             mPlaylistsUri = Playlists.getContentUri(volumeName);
 
             mCaseInsensitivePaths = true;
diff --git a/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml b/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml
index 7dfa53e..6504435 100644
--- a/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml
+++ b/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml
@@ -21,13 +21,15 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
               android:layout_width="match_parent" 
               android:layout_height="match_parent"
-              android:orientation="vertical"
-              android:padding="16dp" >
+              android:orientation="vertical" >
 
-    <ScrollView 
+    <ScrollView
             android:layout_height="0dp"
             android:layout_weight="1"
-            android:layout_width="match_parent">
+            android:layout_width="match_parent"
+            android:padding="16dp"
+            android:clipToPadding="false" >
+
         <LinearLayout
                 android:orientation="vertical"
                 android:layout_height="wrap_content"
@@ -76,24 +78,29 @@
         </LinearLayout>
     </ScrollView>
 
+    <!-- button bar divider -->
+    <View android:background="?android:attr/dividerHorizontal"
+          android:layout_height="1dp"
+          android:layout_width="match_parent" />
+
+    <!-- button bar -->
     <LinearLayout android:orientation="horizontal"
+                  style="?android:attr/buttonBarStyle"                 
                   android:layout_height="wrap_content"
                   android:layout_width="match_parent"
                   android:layout_gravity="bottom">
 
-    <Button android:id="@+id/button_allow"
-            android:filterTouchesWhenObscured="true"
-            android:text="@string/allow_backup_button_label"
-            android:layout_below="@id/package_name"
+    <Button android:id="@+id/button_deny"
+            style="?android:attr/buttonBarButtonStyle"
+            android:text="@string/deny_backup_button_label"
             android:layout_height="wrap_content"
             android:layout_width="0dp"
             android:layout_weight="1" />
 
-    <Button android:id="@+id/button_deny"
-            android:text="@string/deny_backup_button_label"
-            android:layout_below="@id/package_name"
-            android:layout_toRightOf="@id/button_allow"
-            android:layout_alignTop="@id/button_allow"
+    <Button android:id="@+id/button_allow"
+            style="?android:attr/buttonBarButtonStyle"
+            android:filterTouchesWhenObscured="true"
+            android:text="@string/allow_backup_button_label"
             android:layout_height="wrap_content"
             android:layout_width="0dp"
             android:layout_weight="1" />
diff --git a/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml b/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml
index 4927cbb..3522e7c 100644
--- a/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml
+++ b/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml
@@ -76,24 +76,29 @@
         </LinearLayout>
     </ScrollView>
 
+    <!-- button bar divider -->
+    <View android:background="?android:attr/dividerHorizontal"
+          android:layout_height="1dp"
+          android:layout_width="match_parent" />
+
+    <!-- button bar -->
     <LinearLayout android:orientation="horizontal"
+                  style="?android:attr/buttonBarStyle"                 
                   android:layout_height="wrap_content"
                   android:layout_width="match_parent"
                   android:layout_gravity="bottom">
 
-        <Button android:id="@+id/button_allow"
-                android:filterTouchesWhenObscured="true"
-                android:text="@string/allow_restore_button_label"
-                android:layout_below="@id/package_name"
+        <Button android:id="@+id/button_deny"
+                style="?android:attr/buttonBarButtonStyle"
+                android:text="@string/deny_restore_button_label"
                 android:layout_height="wrap_content"
                 android:layout_width="0dp"
                 android:layout_weight="1" />
 
-        <Button android:id="@+id/button_deny"
-                android:text="@string/deny_restore_button_label"
-                android:layout_below="@id/package_name"
-                android:layout_toRightOf="@id/button_allow"
-                android:layout_alignTop="@id/button_allow"
+        <Button android:id="@+id/button_allow"
+                style="?android:attr/buttonBarButtonStyle"
+                android:filterTouchesWhenObscured="true"
+                android:text="@string/allow_restore_button_label"
                 android:layout_height="wrap_content"
                 android:layout_width="0dp"
                 android:layout_weight="1" />
diff --git a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
index f65a62f..5448e0b 100644
--- a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
+++ b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
@@ -48,6 +48,8 @@
     static final String TAG = "BackupRestoreConfirmation";
     static final boolean DEBUG = true;
 
+    static final String DID_ACKNOWLEDGE = "did_acknowledge";
+
     static final int MSG_START_BACKUP = 1;
     static final int MSG_BACKUP_PACKAGE = 2;
     static final int MSG_END_BACKUP = 3;
@@ -149,7 +151,13 @@
         mBackupManager = IBackupManager.Stub.asInterface(ServiceManager.getService(Context.BACKUP_SERVICE));
 
         mHandler = new ObserverHandler(getApplicationContext());
-        mObserver = new FullObserver();
+        final Object oldObserver = getLastNonConfigurationInstance();
+        if (oldObserver == null) {
+            mObserver = new FullObserver(mHandler);
+        } else {
+            mObserver = (FullObserver) oldObserver;
+            mObserver.setHandler(mHandler);
+        }
 
         setContentView(layoutId);
 
@@ -189,16 +197,24 @@
                 mDenyButton.setEnabled(false);
             }
         });
+
+        // if we're a relaunch we may need to adjust button enable state
+        if (icicle != null) {
+            mDidAcknowledge = icicle.getBoolean(DID_ACKNOWLEDGE, false);
+            mAllowButton.setEnabled(!mDidAcknowledge);
+            mDenyButton.setEnabled(!mDidAcknowledge);
+        }
+    }
+
+    // Preserve the restore observer callback binder across activity relaunch
+    @Override
+    public Object onRetainNonConfigurationInstance() {
+        return mObserver;
     }
 
     @Override
-    public void onStop() {
-        super.onStop();
-
-        // We explicitly equate departure from the UI with refusal.  This includes the
-        // implicit configuration-changed stop/restart cycle.
-        sendAcknowledgement(mToken, false, null);
-        finish();
+    protected void onSaveInstanceState(Bundle outState) {
+        outState.putBoolean(DID_ACKNOWLEDGE, mDidAcknowledge);
     }
 
     void sendAcknowledgement(int token, boolean allow, IFullBackupRestoreObserver observer) {
@@ -230,6 +246,16 @@
      * the notifications onto the main thread.
      */
     class FullObserver extends IFullBackupRestoreObserver.Stub {
+        private Handler mHandler;
+
+        public FullObserver(Handler h) {
+            mHandler = h;
+        }
+
+        public void setHandler(Handler h) {
+            mHandler = h;
+        }
+
         //
         // IFullBackupRestoreObserver implementation
         //
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 7cc5ff7..e1231a5 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -93,9 +93,12 @@
             }
 
             super.onCreate(surfaceHolder);
-            IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED);
-            mReceiver = new WallpaperObserver();
-            registerReceiver(mReceiver, filter, null, mHandler);
+            
+            // Don't need this currently because the wallpaper service
+            // will restart the image wallpaper whenever the image changes.
+            //IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED);
+            //mReceiver = new WallpaperObserver();
+            //registerReceiver(mReceiver, filter, null, mHandler);
 
             updateSurfaceSize(surfaceHolder);
         }
@@ -103,7 +106,9 @@
         @Override
         public void onDestroy() {
             super.onDestroy();
-            unregisterReceiver(mReceiver);
+            if (mReceiver != null) {
+                unregisterReceiver(mReceiver);
+            }
         }
 
         @Override
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 2e3d6dd..8b7d3a8 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -2034,6 +2034,15 @@
                 boolean compressing = COMPRESS_FULL_BACKUPS;
                 OutputStream finalOutput = ofstream;
 
+                // Verify that the given password matches the currently-active
+                // backup password, if any
+                if (hasBackupPassword()) {
+                    if (!passwordMatchesSaved(mCurrentPassword, PBKDF2_HASH_ROUNDS)) {
+                        if (DEBUG) Slog.w(TAG, "Backup password mismatch; aborting");
+                        return;
+                    }
+                }
+
                 // Write the global file header.  All strings are UTF-8 encoded; lines end
                 // with a '\n' byte.  Actual backup data begins immediately following the
                 // final '\n'.
@@ -2068,15 +2077,6 @@
                 try {
                     // Set up the encryption stage if appropriate, and emit the correct header
                     if (encrypting) {
-                        // Verify that the given password matches the currently-active
-                        // backup password, if any
-                        if (hasBackupPassword()) {
-                            if (!passwordMatchesSaved(mCurrentPassword, PBKDF2_HASH_ROUNDS)) {
-                                if (DEBUG) Slog.w(TAG, "Backup password mismatch; aborting");
-                                return;
-                            }
-                        }
-
                         finalOutput = emitAesBackupHeader(headerbuf, finalOutput);
                     } else {
                         headerbuf.append("none\n");
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index 2460fd6..9765f2a 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -118,6 +118,10 @@
                         File changedFile = new File(WALLPAPER_DIR, path);
                         if (WALLPAPER_FILE.equals(changedFile)) {
                             notifyCallbacksLocked();
+                            if (mWallpaperComponent == null ||
+                                    mWallpaperComponent.equals(mImageWallpaperComponent)) {
+                                bindWallpaperComponentLocked(mWallpaperComponent, true);
+                            }
                         }
                     }
                 }
@@ -191,7 +195,7 @@
                     if (!mWallpaperUpdating && (mLastDiedTime+MIN_WALLPAPER_CRASH_TIME)
                                 > SystemClock.uptimeMillis()) {
                         Slog.w(TAG, "Reverting to built-in wallpaper!");
-                        bindWallpaperComponentLocked(null);
+                        bindWallpaperComponentLocked(null, true);
                     }
                 }
             }
@@ -220,7 +224,7 @@
                     mWallpaperUpdating = false;
                     ComponentName comp = mWallpaperComponent;
                     clearWallpaperComponentLocked();
-                    bindWallpaperComponentLocked(comp);
+                    bindWallpaperComponentLocked(comp, false);
                 }
             }
         }
@@ -312,11 +316,11 @@
         if (DEBUG) Slog.v(TAG, "systemReady");
         synchronized (mLock) {
             try {
-                bindWallpaperComponentLocked(mNextWallpaperComponent);
+                bindWallpaperComponentLocked(mNextWallpaperComponent, false);
             } catch (RuntimeException e) {
                 Slog.w(TAG, "Failure starting previous wallpaper", e);
                 try {
-                    bindWallpaperComponentLocked(null);
+                    bindWallpaperComponentLocked(null, false);
                 } catch (RuntimeException e2) {
                     Slog.w(TAG, "Failure starting default wallpaper", e2);
                     clearWallpaperComponentLocked();
@@ -339,7 +343,7 @@
         }
         final long ident = Binder.clearCallingIdentity();
         try {
-            bindWallpaperComponentLocked(null);
+            bindWallpaperComponentLocked(null, false);
         } catch (IllegalArgumentException e) {
             // This can happen if the default wallpaper component doesn't
             // exist.  This should be a system configuration problem, but
@@ -430,7 +434,7 @@
                 ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name);
                 if (pfd != null) {
                     // Bind the wallpaper to an ImageWallpaper
-                    bindWallpaperComponentLocked(mImageWallpaperComponent);
+                    bindWallpaperComponentLocked(mImageWallpaperComponent, false);
                     saveSettingsLocked();
                 }
                 return pfd;
@@ -459,28 +463,30 @@
         synchronized (mLock) {
             final long ident = Binder.clearCallingIdentity();
             try {
-                bindWallpaperComponentLocked(name);
+                bindWallpaperComponentLocked(name, false);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
         }
     }
     
-    void bindWallpaperComponentLocked(ComponentName componentName) {
+    void bindWallpaperComponentLocked(ComponentName componentName, boolean force) {
         if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
         
         // Has the component changed?
-        if (mWallpaperConnection != null) {
-            if (mWallpaperComponent == null) {
-                if (componentName == null) {
-                    if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: still using default");
-                    // Still using default wallpaper.
+        if (!force) {
+            if (mWallpaperConnection != null) {
+                if (mWallpaperComponent == null) {
+                    if (componentName == null) {
+                        if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: still using default");
+                        // Still using default wallpaper.
+                        return;
+                    }
+                } else if (mWallpaperComponent.equals(componentName)) {
+                    // Changing to same wallpaper.
+                    if (DEBUG) Slog.v(TAG, "same wallpaper");
                     return;
                 }
-            } else if (mWallpaperComponent.equals(componentName)) {
-                // Changing to same wallpaper.
-                if (DEBUG) Slog.v(TAG, "same wallpaper");
-                return;
             }
         }
         
@@ -599,7 +605,7 @@
         } catch (RemoteException e) {
             Slog.w(TAG, "Failed attaching wallpaper; clearing", e);
             if (!mWallpaperUpdating) {
-                bindWallpaperComponentLocked(null);
+                bindWallpaperComponentLocked(null, false);
             }
         }
     }
@@ -645,7 +651,8 @@
             out.attribute(null, "width", Integer.toString(mWidth));
             out.attribute(null, "height", Integer.toString(mHeight));
             out.attribute(null, "name", mName);
-            if (mWallpaperComponent != null) {
+            if (mWallpaperComponent != null &&
+                    !mWallpaperComponent.equals(mImageWallpaperComponent)) {
                 out.attribute(null, "component",
                         mWallpaperComponent.flattenToShortString());
             }
@@ -691,6 +698,10 @@
                         mNextWallpaperComponent = comp != null
                                 ? ComponentName.unflattenFromString(comp)
                                 : null;
+                        if (mNextWallpaperComponent == null ||
+                                "android".equals(mNextWallpaperComponent.getPackageName())) {
+                            mNextWallpaperComponent = mImageWallpaperComponent;
+                        }
                           
                         if (DEBUG) {
                             Slog.v(TAG, "mWidth:" + mWidth);
@@ -749,12 +760,12 @@
             if (mNextWallpaperComponent != null && 
                     !mNextWallpaperComponent.equals(mImageWallpaperComponent)) {
                 try {
-                    bindWallpaperComponentLocked(mNextWallpaperComponent);
+                    bindWallpaperComponentLocked(mNextWallpaperComponent, false);
                 } catch (IllegalArgumentException e) {
                     // No such live wallpaper or other failure; fall back to the default
                     // live wallpaper (since the profile being restored indicated that the
                     // user had selected a live rather than static one).
-                    bindWallpaperComponentLocked(null);
+                    bindWallpaperComponentLocked(null, false);
                 }
                 success = true;
             } else {
@@ -769,7 +780,7 @@
                 }
                 if (DEBUG) Slog.v(TAG, "settingsRestored: success=" + success);
                 if (success) {
-                    bindWallpaperComponentLocked(mImageWallpaperComponent);
+                    bindWallpaperComponentLocked(null, false);
                 }
             }
         }
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 242a93d..a80a2b8 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -289,6 +289,10 @@
                     mWifiStateMachine.startWps(msg.replyTo, (WpsConfiguration)msg.obj);
                     break;
                 }
+                case WifiManager.CMD_DISABLE_NETWORK: {
+                    mWifiStateMachine.disableNetwork(msg.replyTo, msg.arg1, msg.arg2);
+                    break;
+                }
                 default: {
                     Slog.d(TAG, "WifiServicehandler.handleMessage ignoring msg=" + msg);
                     break;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 14c6306..ba8b58b 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -3317,6 +3317,14 @@
         return infos;
     }
 
+    public long[] getProcessPss(int[] pids) throws RemoteException {
+        long[] pss = new long[pids.length];
+        for (int i=pids.length-1; i>=0; i--) {
+            pss[i] = Debug.getPss(pids[i]);
+        }
+        return pss;
+    }
+
     public void killApplicationProcess(String processName, int uid) {
         if (processName == null) {
             return;
@@ -8868,15 +8876,15 @@
         }
     }
 
-    ArrayList<ProcessRecord> collectProcesses(PrintWriter pw, String[] args) {
+    ArrayList<ProcessRecord> collectProcesses(PrintWriter pw, int start, String[] args) {
         ArrayList<ProcessRecord> procs;
         synchronized (this) {
-            if (args != null && args.length > 0
-                    && args[0].charAt(0) != '-') {
+            if (args != null && args.length > start
+                    && args[start].charAt(0) != '-') {
                 procs = new ArrayList<ProcessRecord>();
                 int pid = -1;
                 try {
-                    pid = Integer.parseInt(args[0]);
+                    pid = Integer.parseInt(args[start]);
                 } catch (NumberFormatException e) {
 
                 }
@@ -8884,12 +8892,12 @@
                     ProcessRecord proc = mLruProcesses.get(i);
                     if (proc.pid == pid) {
                         procs.add(proc);
-                    } else if (proc.processName.equals(args[0])) {
+                    } else if (proc.processName.equals(args[start])) {
                         procs.add(proc);
                     }
                 }
                 if (procs.size() <= 0) {
-                    pw.println("No process found for: " + args[0]);
+                    pw.println("No process found for: " + args[start]);
                     return null;
                 }
             } else {
@@ -8901,7 +8909,7 @@
 
     final void dumpGraphicsHardwareUsage(FileDescriptor fd,
             PrintWriter pw, String[] args) {
-        ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
+        ArrayList<ProcessRecord> procs = collectProcesses(pw, 0, args);
         if (procs == null) {
             return;
         }
@@ -8945,18 +8953,21 @@
         }
     }
 
-    final void dumpMemItems(PrintWriter pw, String prefix, ArrayList<MemItem> items) {
-        Collections.sort(items, new Comparator<MemItem>() {
-            @Override
-            public int compare(MemItem lhs, MemItem rhs) {
-                if (lhs.pss < rhs.pss) {
-                    return 1;
-                } else if (lhs.pss > rhs.pss) {
-                    return -1;
+    final void dumpMemItems(PrintWriter pw, String prefix, ArrayList<MemItem> items,
+            boolean sort) {
+        if (sort) {
+            Collections.sort(items, new Comparator<MemItem>() {
+                @Override
+                public int compare(MemItem lhs, MemItem rhs) {
+                    if (lhs.pss < rhs.pss) {
+                        return 1;
+                    } else if (lhs.pss > rhs.pss) {
+                        return -1;
+                    }
+                    return 0;
                 }
-                return 0;
-            }
-        });
+            });
+        }
 
         for (int i=0; i<items.size(); i++) {
             MemItem mi = items.get(i);
@@ -8966,7 +8977,29 @@
 
     final void dumpApplicationMemoryUsage(FileDescriptor fd,
             PrintWriter pw, String prefix, String[] args) {
-        ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
+        boolean dumpAll = false;
+        
+        int opti = 0;
+        while (opti < args.length) {
+            String opt = args[opti];
+            if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
+                break;
+            }
+            opti++;
+            if ("-a".equals(opt)) {
+                dumpAll = true;
+            } else if ("-h".equals(opt)) {
+                pw.println("meminfo dump options: [-a] [process]");
+                pw.println("  -a: include all available information for each process.");
+                pw.println("If [process] is specified it can be the name or ");
+                pw.println("pid of a specific process to dump.");
+                return;
+            } else {
+                pw.println("Unknown argument: " + opt + "; use -h for help");
+            }
+        }
+        
+        ArrayList<ProcessRecord> procs = collectProcesses(pw, opti, args);
         if (procs == null) {
             return;
         }
@@ -8974,7 +9007,11 @@
         final boolean isCheckinRequest = scanArgs(args, "--checkin");
         long uptime = SystemClock.uptimeMillis();
         long realtime = SystemClock.elapsedRealtime();
-        
+
+        if (procs.size() == 1 || isCheckinRequest) {
+            dumpAll = true;
+        }
+
         if (isCheckinRequest) {
             // short checkin version
             pw.println(uptime + "," + realtime);
@@ -8984,29 +9021,53 @@
             pw.println("Uptime: " + uptime + " Realtime: " + realtime);
         }
 
+        String[] innerArgs = new String[args.length-opti];
+        System.arraycopy(args, opti, innerArgs, 0, args.length-opti);
+
         ArrayList<MemItem> procMems = new ArrayList<MemItem>();
         long nativePss=0, dalvikPss=0, otherPss=0;
         long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
 
+        final int[] oomAdj = new int[] {
+            SYSTEM_ADJ, CORE_SERVER_ADJ, FOREGROUND_APP_ADJ,
+            VISIBLE_APP_ADJ, PERCEPTIBLE_APP_ADJ, HEAVY_WEIGHT_APP_ADJ,
+            BACKUP_APP_ADJ, SECONDARY_SERVER_ADJ, HOME_APP_ADJ, EMPTY_APP_ADJ
+        };
+        final String[] oomLabel = new String[] {
+                "System", "Persistent", "Foreground",
+                "Visible", "Perceptible", "Heavy Weight",
+                "Backup", "Services", "Home", "Background"
+        };
+        long oomPss[] = new long[oomLabel.length];
+
+        long totalPss = 0;
+
         for (int i = procs.size() - 1 ; i >= 0 ; i--) {
             ProcessRecord r = procs.get(i);
             if (r.thread != null) {
-                if (!isCheckinRequest) {
+                if (!isCheckinRequest && dumpAll) {
                     pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
                     pw.flush();
                 }
                 Debug.MemoryInfo mi = null;
-                try {
-                    mi = r.thread.dumpMemInfo(fd, args);
-                } catch (RemoteException e) {
-                    if (!isCheckinRequest) {
-                        pw.println("Got RemoteException!");
-                        pw.flush();
+                if (dumpAll) {
+                    try {
+                        mi = r.thread.dumpMemInfo(fd, isCheckinRequest, dumpAll, innerArgs);
+                    } catch (RemoteException e) {
+                        if (!isCheckinRequest) {
+                            pw.println("Got RemoteException!");
+                            pw.flush();
+                        }
                     }
+                } else {
+                    mi = new Debug.MemoryInfo();
+                    Debug.getMemoryInfo(r.pid, mi);
                 }
+
                 if (!isCheckinRequest && mi != null) {
-                    procMems.add(new MemItem(r.processName + " (pid " + r.pid + ")",
-                            mi.getTotalPss()));
+                    long myTotalPss = mi.getTotalPss();
+                    totalPss += myTotalPss;
+                    procMems.add(new MemItem(r.processName + " (pid " + r.pid + ")", myTotalPss));
 
                     nativePss += mi.nativePss;
                     dalvikPss += mi.dalvikPss;
@@ -9016,6 +9077,13 @@
                         miscPss[j] += mem;
                         otherPss -= mem;
                     }
+
+                    for (int oomIndex=0; oomIndex<oomPss.length; oomIndex++) {
+                        if (r.setAdj <= oomAdj[oomIndex] || oomIndex == (oomPss.length-1)) {
+                            oomPss[oomIndex] += myTotalPss;
+                            break;
+                        }
+                    }
                 }
             }
         }
@@ -9030,12 +9098,24 @@
                 catMems.add(new MemItem(Debug.MemoryInfo.getOtherLabel(j), miscPss[j]));
             }
 
+            ArrayList<MemItem> oomMems = new ArrayList<MemItem>();
+            for (int j=0; j<oomPss.length; j++) {
+                if (oomPss[j] != 0) {
+                    oomMems.add(new MemItem(oomLabel[j], oomPss[j]));
+                }
+            }
+
             pw.println();
             pw.println("Total PSS by process:");
-            dumpMemItems(pw, "  ", procMems);
+            dumpMemItems(pw, "  ", procMems, true);
+            pw.println();
+            pw.println("Total PSS by OOM adjustment:");
+            dumpMemItems(pw, "  ", oomMems, false);
             pw.println();
             pw.println("Total PSS by category:");
-            dumpMemItems(pw, "  ", catMems);
+            dumpMemItems(pw, "  ", catMems, true);
+            pw.println();
+            pw.print("Total PSS: "); pw.print(totalPss); pw.println(" Kb");
         }
     }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
index 4d86903..134227a 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
@@ -484,8 +484,7 @@
         // Note: it needs to be confirmed which CDMA network types
         // can support voice and data calls concurrently.
         // For the time-being, the return value will be false.
-        // return (networkType >= ServiceState.RADIO_TECHNOLOGY_LTE);
-        return false;
+        return (networkType == ServiceState.RADIO_TECHNOLOGY_LTE);
     }
 
     /**
diff --git a/tests/BiDiTests/res/layout/basic.xml b/tests/BiDiTests/res/layout/basic.xml
index ed91c49..18f193e 100644
--- a/tests/BiDiTests/res/layout/basic.xml
+++ b/tests/BiDiTests/res/layout/basic.xml
@@ -34,17 +34,32 @@
                     android:textSize="32dip"
                     />
 
-            <TextView android:id="@+id/textview"
+            <TextView android:id="@+id/textview_ltr"
                       android:layout_height="wrap_content"
                       android:layout_width="wrap_content"
                       android:textSize="32dip"
-                      android:text="@string/textview_text"
+                      android:text="@string/textview_ltr_text"
                     />
 
-            <EditText android:id="@+id/edittext"
+            <EditText android:id="@+id/edittext_ltr"
                       android:layout_height="wrap_content"
                       android:layout_width="match_parent"
                       android:textSize="32dip"
+                      android:textDirection="ltr"
+                    />
+
+            <TextView android:id="@+id/textview_rtl"
+                      android:layout_height="wrap_content"
+                      android:layout_width="wrap_content"
+                      android:textSize="32dip"
+                      android:text="@string/textview_rtl_text"
+                    />
+
+            <EditText android:id="@+id/edittext_rtl"
+                      android:layout_height="wrap_content"
+                      android:layout_width="match_parent"
+                      android:textSize="32dip"
+                      android:textDirection="rtl"
                     />
 
         </LinearLayout>
diff --git a/tests/BiDiTests/res/values/strings.xml b/tests/BiDiTests/res/values/strings.xml
index 1f6be7f..f4ce0f7 100644
--- a/tests/BiDiTests/res/values/strings.xml
+++ b/tests/BiDiTests/res/values/strings.xml
@@ -25,6 +25,8 @@
     <string name="button_requestlayout_text">Request Layout</string>
     <string name="button_alert_dialog_text">AlertDialog</string>
     <string name="textview_text">This is a text for a TextView</string>
+    <string name="textview_ltr_text">This is a text for a LTR TextView</string>
+    <string name="textview_rtl_text">This is a text for a RTL TextView</string>
     <string name="edittext_text">mmmmmmmmmmmmmmmmmmmmmmmm</string>
     <string name="normal_text">Normal String</string>
     <string name="normal_long_text">mmmmmmmmmmmmmmmmmmmmmmmm</string>
diff --git a/wifi/java/android/net/wifi/SupplicantStateTracker.java b/wifi/java/android/net/wifi/SupplicantStateTracker.java
index 9168e62..cbd284c 100644
--- a/wifi/java/android/net/wifi/SupplicantStateTracker.java
+++ b/wifi/java/android/net/wifi/SupplicantStateTracker.java
@@ -89,7 +89,7 @@
             mNetworksDisabledDuringConnect = false;
         }
         /* Disable failed network */
-        WifiConfigStore.disableNetwork(netId);
+        WifiConfigStore.disableNetwork(netId, WifiConfiguration.DISABLED_AUTH_FAILURE);
     }
 
     private void transitionOnSupplicantStateChange(StateChangeResult stateChangeResult) {
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index d83b968..9a51d5e 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -195,8 +195,9 @@
      * or a failure event from supplicant
      *
      * @param config The configuration details in WifiConfiguration
+     * @return the networkId now associated with the specified configuration
      */
-    static void selectNetwork(WifiConfiguration config) {
+    static int selectNetwork(WifiConfiguration config) {
         if (config != null) {
             NetworkUpdateResult result = addOrUpdateNetworkNative(config);
             int netId = result.getNetworkId();
@@ -205,7 +206,9 @@
             } else {
                 Log.e(TAG, "Failed to update network " + config);
             }
+            return netId;
         }
+        return INVALID_NETWORK_ID;
     }
 
     /**
@@ -351,10 +354,22 @@
      * @param netId network to be disabled
      */
     static boolean disableNetwork(int netId) {
+        return disableNetwork(netId, WifiConfiguration.DISABLED_UNKNOWN_REASON);
+    }
+
+    /**
+     * Disable a network. Note that there is no saveConfig operation.
+     * @param netId network to be disabled
+     * @param reason reason code network was disabled
+     */
+    static boolean disableNetwork(int netId, int reason) {
         boolean ret = WifiNative.disableNetworkCommand(netId);
         synchronized (sConfiguredNetworks) {
             WifiConfiguration config = sConfiguredNetworks.get(netId);
-            if (config != null) config.status = Status.DISABLED;
+            if (config != null) {
+                config.status = Status.DISABLED;
+                config.disableReason = reason;
+            }
         }
         sendConfiguredNetworksChangedBroadcast();
         return ret;
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 28a5bc6..d2a0b30 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -211,6 +211,15 @@
         public static final String[] strings = { "current", "disabled", "enabled" };
     }
 
+    /** @hide */
+    public static final int DISABLED_UNKNOWN_REASON                         = 0;
+    /** @hide */
+    public static final int DISABLED_DNS_FAILURE                            = 1;
+    /** @hide */
+    public static final int DISABLED_DHCP_FAILURE                           = 2;
+    /** @hide */
+    public static final int DISABLED_AUTH_FAILURE                           = 3;
+
     /**
      * The ID number that the supplicant uses to identify this
      * network configuration entry. This must be passed as an argument
@@ -223,6 +232,14 @@
      * @see Status
      */
     public int status;
+
+    /**
+     * The code referring to a reason for disabling the network
+     * Valid when {@link #status} == Status.DISABLED
+     * @hide
+     */
+    public int disableReason;
+
     /**
      * The network's SSID. Can either be an ASCII string,
      * which must be enclosed in double quotation marks
@@ -351,6 +368,7 @@
         BSSID = null;
         priority = 0;
         hiddenSSID = false;
+        disableReason = DISABLED_UNKNOWN_REASON;
         allowedKeyManagement = new BitSet();
         allowedProtocols = new BitSet();
         allowedAuthAlgorithms = new BitSet();
@@ -367,12 +385,13 @@
         linkProperties = new LinkProperties();
     }
 
+    @Override
     public String toString() {
-        StringBuffer sbuf = new StringBuffer();
+        StringBuilder sbuf = new StringBuilder();
         if (this.status == WifiConfiguration.Status.CURRENT) {
             sbuf.append("* ");
         } else if (this.status == WifiConfiguration.Status.DISABLED) {
-            sbuf.append("- ");
+            sbuf.append("- DSBLE: ").append(this.disableReason).append(" ");
         }
         sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID).
                 append(" BSSID: ").append(this.BSSID).append(" PRIO: ").append(this.priority).
@@ -541,6 +560,7 @@
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(networkId);
         dest.writeInt(status);
+        dest.writeInt(disableReason);
         dest.writeString(SSID);
         dest.writeString(BSSID);
         dest.writeString(preSharedKey);
@@ -571,6 +591,7 @@
                 WifiConfiguration config = new WifiConfiguration();
                 config.networkId = in.readInt();
                 config.status = in.readInt();
+                config.disableReason = in.readInt();
                 config.SSID = in.readString();
                 config.BSSID = in.readString();
                 config.preSharedKey = in.readString();
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 7bb927b..d5b404e 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -70,6 +70,7 @@
     private InetAddress mIpAddress;
 
     private String mMacAddress;
+    private boolean mExplicitConnect;
 
     WifiInfo() {
         mSSID = null;
@@ -79,6 +80,7 @@
         mRssi = -9999;
         mLinkSpeed = -1;
         mHiddenSSID = false;
+        mExplicitConnect = false;
     }
 
     /**
@@ -96,6 +98,7 @@
             mLinkSpeed = source.mLinkSpeed;
             mIpAddress = source.mIpAddress;
             mMacAddress = source.mMacAddress;
+            mExplicitConnect = source.mExplicitConnect;
         }
     }
 
@@ -172,6 +175,22 @@
         mNetworkId = id;
     }
 
+
+    /**
+     * @hide
+     */
+    public boolean isExplicitConnect() {
+        return mExplicitConnect;
+    }
+
+    /**
+     * @hide
+     */
+    public void setExplicitConnect(boolean explicitConnect) {
+        this.mExplicitConnect = explicitConnect;
+    }
+
+
     /**
      * Each configured network has a unique small integer ID, used to identify
      * the network when performing operations on the supplicant. This method
@@ -260,7 +279,8 @@
             append(mSupplicantState == null ? none : mSupplicantState).
             append(", RSSI: ").append(mRssi).
             append(", Link speed: ").append(mLinkSpeed).
-            append(", Net ID: ").append(mNetworkId);
+            append(", Net ID: ").append(mNetworkId).
+            append(", Explicit connect: ").append(mExplicitConnect);
 
         return sb.toString();
     }
@@ -284,6 +304,7 @@
         dest.writeString(getSSID());
         dest.writeString(mBSSID);
         dest.writeString(mMacAddress);
+        dest.writeByte(mExplicitConnect ? (byte)1 : (byte)0);
         mSupplicantState.writeToParcel(dest, flags);
     }
 
@@ -303,6 +324,7 @@
                 info.setSSID(in.readString());
                 info.mBSSID = in.readString();
                 info.mMacAddress = in.readString();
+                info.mExplicitConnect = in.readByte() == 1 ? true : false;
                 info.mSupplicantState = SupplicantState.CREATOR.createFromParcel(in);
                 return info;
             }
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index cd6621f..5f8385c 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -615,6 +615,17 @@
     }
 
     /**
+     * Disable a configured network asynchronously.  This call is for abnormal network
+     * events, and the user may be notified of network change, if they recently attempted
+     * to connect to the specified network.
+     * @param netId the ID of the network as returned by {@link #addNetwork}.
+     * @hide
+     */
+    public void disableNetwork(int netId, int reason) {
+        mAsyncChannel.sendMessage(CMD_DISABLE_NETWORK, netId, reason);
+    }
+
+    /**
      * Disassociate from the currently active access point. This may result
      * in the asynchronous delivery of state change events.
      * @return {@code true} if the operation succeeded
@@ -1058,6 +1069,8 @@
     public static final int CMD_SAVE_NETWORK                = 3;
     /** @hide */
     public static final int CMD_START_WPS                   = 4;
+    /** @hide */
+    public static final int CMD_DISABLE_NETWORK             = 5;
 
     /* Events from WifiService */
     /** @hide */
@@ -1617,4 +1630,4 @@
              return false;
         }
     }
-}
+}
\ No newline at end of file
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 331d5c0..82ff0de 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -68,12 +68,14 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.LruCache;
+import android.util.Slog;
 
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.util.AsyncChannel;
@@ -482,6 +484,11 @@
     private final WorkSource mLastRunningWifiUids = new WorkSource();
 
     private final IBatteryStats mBatteryStats;
+    private boolean mNextWifiActionExplicit = false;
+    private int mLastExplicitNetworkId;
+    private long mLastNetworkChoiceTime;
+    private static final long EXPLICIT_CONNECT_ALLOWED_DELAY_MS = 2 * 60 * 1000;
+
 
     public WifiStateMachine(Context context, String wlanInterface) {
         super(TAG);
@@ -821,7 +828,8 @@
      * @return {@code true} if the operation succeeds, {@code false} otherwise
      */
     public boolean syncDisableNetwork(AsyncChannel channel, int netId) {
-        Message resultMsg = channel.sendMessageSynchronously(CMD_DISABLE_NETWORK, netId);
+        Message resultMsg = channel.sendMessageSynchronously(CMD_DISABLE_NETWORK, netId,
+                WifiConfiguration.DISABLED_UNKNOWN_REASON);
         boolean result = (resultMsg.arg1 != FAILURE);
         resultMsg.recycle();
         return result;
@@ -866,6 +874,12 @@
         sendMessage(obtainMessage(CMD_FORGET_NETWORK, netId, 0));
     }
 
+    public void disableNetwork(Messenger replyTo, int netId, int reason) {
+        Message message = obtainMessage(CMD_DISABLE_NETWORK, netId, reason);
+        message.replyTo = replyTo;
+        sendMessage(message);
+    }
+
     public void startWps(Messenger replyTo, WpsConfiguration config) {
         Message msg = obtainMessage(CMD_START_WPS, config);
         msg.replyTo = replyTo;
@@ -1534,6 +1548,7 @@
         mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
         mWifiInfo.setRssi(MIN_RSSI);
         mWifiInfo.setLinkSpeed(-1);
+        mWifiInfo.setExplicitConnect(false);
 
         /* send event to CM & network change broadcast */
         setNetworkDetailedState(DetailedState.DISCONNECTED);
@@ -1631,7 +1646,8 @@
         if (++mReconnectCount > getMaxDhcpRetries()) {
             Log.e(TAG, "Failed " +
                     mReconnectCount + " times, Disabling " + mLastNetworkId);
-            WifiConfigStore.disableNetwork(mLastNetworkId);
+            WifiConfigStore.disableNetwork(mLastNetworkId,
+                    WifiConfiguration.DISABLED_DHCP_FAILURE);
             mReconnectCount = 0;
         }
 
@@ -2169,7 +2185,7 @@
                     WifiConfigStore.enableAllNetworks();
                     break;
                 case CMD_DISABLE_NETWORK:
-                    ok = WifiConfigStore.disableNetwork(message.arg1);
+                    ok = WifiConfigStore.disableNetwork(message.arg1, message.arg2);
                     mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE);
                     break;
                 case CMD_BLACKLIST_NETWORK:
@@ -2605,7 +2621,7 @@
                      * a connection to the enabled network.
                      */
                     if (config != null) {
-                        WifiConfigStore.selectNetwork(config);
+                        netId = WifiConfigStore.selectNetwork(config);
                     } else {
                         WifiConfigStore.selectNetwork(netId);
                     }
@@ -2614,7 +2630,10 @@
                     mSupplicantStateTracker.sendMessage(CMD_CONNECT_NETWORK);
 
                     WifiNative.reconnectCommand();
-
+                    mLastExplicitNetworkId = netId;
+                    mLastNetworkChoiceTime  = SystemClock.elapsedRealtime();
+                    mNextWifiActionExplicit = true;
+                    Slog.d(TAG, "Setting wifi connect explicit for netid " + netId);
                     /* Expect a disconnection from the old connection */
                     transitionTo(mDisconnectingState);
                     break;
@@ -2636,6 +2655,13 @@
                     mWifiInfo.setSSID(fetchSSID());
                     mWifiInfo.setBSSID(mLastBssid);
                     mWifiInfo.setNetworkId(mLastNetworkId);
+                    if (mNextWifiActionExplicit &&
+                        mWifiInfo.getNetworkId() == mLastExplicitNetworkId &&
+                        SystemClock.elapsedRealtime() < mLastNetworkChoiceTime +
+                                                            EXPLICIT_CONNECT_ALLOWED_DELAY_MS) {
+                        mWifiInfo.setExplicitConnect(true);
+                    }
+                    mNextWifiActionExplicit = false;
                     /* send event to CM & network change broadcast */
                     setNetworkDetailedState(DetailedState.OBTAINING_IPADDR);
                     sendNetworkStateChangeBroadcast(mLastBssid);
diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
index 168c68b..5c8926c 100644
--- a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
@@ -70,6 +70,7 @@
     private static final boolean VDBG = false;
     private static final boolean DBG = true;
     private static final String WWSM_TAG = "WifiWatchdogStateMachine";
+    private static final String WATCHDOG_NOTIFICATION_ID = "Android.System.WifiWatchdog";
 
     private static final int WIFI_SIGNAL_LEVELS = 4;
     /**
@@ -157,7 +158,7 @@
     /**
      * The {@link WifiInfo} object passed to WWSM on network broadcasts
      */
-    private WifiInfo mInitialConnInfo;
+    private WifiInfo mConnectionInfo;
     private int mNetEventCounter = 0;
 
     /**
@@ -173,7 +174,9 @@
      * It triggers a disableNetwork call if a DNS check fails.
      */
     public boolean mDisableAPNextFailure = false;
-    public ConnectivityManager mConnectivityManager;
+    private ConnectivityManager mConnectivityManager;
+    private boolean mNotificationShown;
+    public boolean mHasConnectedWifiManager = false;
 
     /**
      * STATE MAP
@@ -212,8 +215,6 @@
 
         setInitialState(mWatchdogDisabledState);
         updateSettings();
-        mShowDisabledNotification = getSettingsBoolean(mContentResolver,
-                Settings.Secure.WIFI_WATCHDOG_SHOW_DISABLED_NETWORK_POPUP, true);
     }
 
     public static WifiWatchdogStateMachine makeWifiWatchdogStateMachine(Context context) {
@@ -318,6 +319,9 @@
         mContext.getContentResolver().registerContentObserver(
                 Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL),
                 false, contentObserver);
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_SHOW_DISABLED_NETWORK_POPUP)
+                , false, contentObserver);
     }
 
     /**
@@ -356,7 +360,7 @@
     public void dump(PrintWriter pw) {
         pw.print("WatchdogStatus: ");
         pw.print("State " + getCurrentState());
-        pw.println(", network [" + mInitialConnInfo + "]");
+        pw.println(", network [" + mConnectionInfo + "]");
         pw.print("checkFailures   " + mNumCheckFailures);
         pw.println(", bssids: " + mBssids);
         pw.println("lastSingleCheck: " + mOnlineWatchState.lastCheckTime);
@@ -396,6 +400,8 @@
         mWalledGardenIntervalMs = Secure.getLong(mContentResolver,
                 Secure.WIFI_WATCHDOG_WALLED_GARDEN_INTERVAL_MS,
                 DEFAULT_WALLED_GARDEN_INTERVAL_MS);
+        mShowDisabledNotification = getSettingsBoolean(mContentResolver,
+                Settings.Secure.WIFI_WATCHDOG_SHOW_DISABLED_NETWORK_POPUP, true);
     }
 
     /**
@@ -420,17 +426,42 @@
     }
 
     /**
-   *
-   */
+     * Uses {@link #mConnectionInfo}.
+     */
+    private void updateBssids() {
+        String curSsid = mConnectionInfo.getSSID();
+        List<ScanResult> results = mWifiManager.getScanResults();
+        int oldNumBssids = mBssids.size();
+
+        if (results == null) {
+            if (DBG) {
+                Slog.d(WWSM_TAG, "updateBssids: Got null scan results!");
+            }
+            return;
+        }
+
+        for (ScanResult result : results) {
+            if (result == null || result.SSID == null) {
+                if (DBG) {
+                    Slog.d(WWSM_TAG, "Received invalid scan result: " + result);
+                }
+                continue;
+            }
+            if (curSsid.equals(result.SSID))
+                mBssids.add(result.BSSID);
+        }
+    }
+
     private void resetWatchdogState() {
         if (VDBG) {
             Slog.v(WWSM_TAG, "Resetting watchdog state...");
         }
-        mInitialConnInfo = null;
+        mConnectionInfo = null;
         mDisableAPNextFailure = false;
         mLastWalledGardenCheckTime = null;
         mNumCheckFailures = 0;
         mBssids.clear();
+        cancelNetworkNotification();
     }
 
     private void popUpBrowser() {
@@ -441,11 +472,11 @@
         mContext.startActivity(intent);
     }
 
-    private void displayDisabledNetworkNotification() {
+    private void displayDisabledNetworkNotification(String ssid) {
         Resources r = Resources.getSystem();
         CharSequence title =
                 r.getText(com.android.internal.R.string.wifi_watchdog_network_disabled);
-        CharSequence msg =
+        String msg = ssid +
                 r.getText(com.android.internal.R.string.wifi_watchdog_network_disabled_detailed);
 
         Notification wifiDisabledWarning = new Notification.Builder(mContext)
@@ -455,7 +486,7 @@
             .setContentTitle(title)
             .setContentText(msg)
             .setContentIntent(PendingIntent.getActivity(mContext, 0,
-                    new Intent(Settings.ACTION_WIFI_IP_SETTINGS)
+                    new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK)
                         .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0))
             .setWhen(System.currentTimeMillis())
             .setAutoCancel(true)
@@ -464,7 +495,17 @@
         NotificationManager notificationManager = (NotificationManager) mContext
                 .getSystemService(Context.NOTIFICATION_SERVICE);
 
-        notificationManager.notify("WifiWatchdog", wifiDisabledWarning.icon, wifiDisabledWarning);
+        notificationManager.notify(WATCHDOG_NOTIFICATION_ID, 1, wifiDisabledWarning);
+        mNotificationShown = true;
+    }
+
+    public void cancelNetworkNotification() {
+        if (mNotificationShown) {
+            NotificationManager notificationManager = (NotificationManager) mContext
+                    .getSystemService(Context.NOTIFICATION_SERVICE);
+            notificationManager.cancel(WATCHDOG_NOTIFICATION_ID, 1);
+            mNotificationShown = false;
+        }
     }
 
     /**
@@ -537,6 +578,7 @@
 
                     switch (networkInfo.getState()) {
                         case CONNECTED:
+                            cancelNetworkNotification();
                             WifiInfo wifiInfo = (WifiInfo)
                                 stateChangeIntent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
                             if (wifiInfo == null) {
@@ -551,6 +593,8 @@
                             }
 
                             initConnection(wifiInfo);
+                            mConnectionInfo = wifiInfo;
+                            updateBssids();
                             transitionTo(mDnsCheckingState);
                             mNetEventCounter++;
                             return HANDLED;
@@ -579,16 +623,15 @@
          */
         private void initConnection(WifiInfo wifiInfo) {
             if (VDBG) {
-                Slog.v(WWSM_TAG, "Connected:: old " + wifiInfoToStr(mInitialConnInfo) +
+                Slog.v(WWSM_TAG, "Connected:: old " + wifiInfoToStr(mConnectionInfo) +
                         " ==> new " + wifiInfoToStr(wifiInfo));
             }
 
-            if (mInitialConnInfo == null || !wifiInfo.getSSID().equals(mInitialConnInfo.getSSID())) {
+            if (mConnectionInfo == null || !wifiInfo.getSSID().equals(mConnectionInfo.getSSID())) {
                 resetWatchdogState();
-            } else if (!wifiInfo.getBSSID().equals(mInitialConnInfo.getBSSID())) {
+            } else if (!wifiInfo.getBSSID().equals(mConnectionInfo.getBSSID())) {
                 mDisableAPNextFailure = false;
             }
-            mInitialConnInfo = wifiInfo;
         }
 
         @Override
@@ -606,27 +649,7 @@
         public boolean processMessage(Message msg) {
             switch (msg.what) {
                 case EVENT_SCAN_RESULTS_AVAILABLE:
-                    String curSsid = mInitialConnInfo.getSSID();
-                    List<ScanResult> results = mWifiManager.getScanResults();
-                    int oldNumBssids = mBssids.size();
-
-                    if (results == null) {
-                        if (DBG) {
-                            Slog.d(WWSM_TAG, "updateBssids: Got null scan results!");
-                        }
-                        return HANDLED;
-                    }
-
-                    for (ScanResult result : results) {
-                        if (result == null || result.SSID == null) {
-                            if (VDBG) {
-                                Slog.v(WWSM_TAG, "Received invalid scan result: " + result);
-                            }
-                            continue;
-                        }
-                        if (curSsid.equals(result.SSID))
-                            mBssids.add(result.BSSID);
-                    }
+                    updateBssids();
                     return HANDLED;
                 case EVENT_WATCHDOG_SETTINGS_CHANGE:
                     // Stop current checks, but let state update
@@ -635,7 +658,6 @@
             }
             return NOT_HANDLED;
         }
-
     }
 
     class DnsCheckingState extends State {
@@ -653,7 +675,7 @@
             if (DBG) {
                 Slog.d(WWSM_TAG, "Starting DNS pings at " + SystemClock.elapsedRealtime());
                 dnsCheckLogStr = String.format("Pinging %s on ssid [%s]: ",
-                        dns, mInitialConnInfo.getSSID());
+                        mDnsPinger.getDns(), mConnectionInfo.getSSID());
             }
 
             for (int i=0; i < mNumDnsPings; i++) {
@@ -905,7 +927,8 @@
                 return HANDLED;
             }
 
-            if (mDisableAPNextFailure || mNumCheckFailures >= mMaxSsidBlacklists) {
+            if (mDisableAPNextFailure || mNumCheckFailures >= mBssids.size()
+                    || mNumCheckFailures >= mMaxSsidBlacklists) {
                 if (hasNoMobileData()) {
                     Slog.w(WWSM_TAG, "Would disable bad network, but device has no mobile data!" +
                             "  Going idle...");
@@ -913,23 +936,26 @@
                     transitionTo(mNotConnectedState);
                     return HANDLED;
                 }
+
                 // TODO : Unban networks if they had low signal ?
-                Slog.i(WWSM_TAG, "Disabling current SSID " + wifiInfoToStr(mInitialConnInfo)
+                Slog.i(WWSM_TAG, "Disabling current SSID " + wifiInfoToStr(mConnectionInfo)
                         + ".  " + "numCheckFailures " + mNumCheckFailures
                         + ", numAPs " + mBssids.size());
-                mWifiManager.disableNetwork(mInitialConnInfo.getNetworkId());
-                if (mShowDisabledNotification) {
-                    displayDisabledNetworkNotification();
-                    mShowDisabledNotification = false;
-                    putSettingsBoolean(mContentResolver,
-                            Settings.Secure.WIFI_WATCHDOG_SHOW_DISABLED_NETWORK_POPUP, false);
+                int networkId = mConnectionInfo.getNetworkId();
+                if (!mHasConnectedWifiManager) {
+                    mWifiManager.asyncConnect(mContext, getHandler());
+                    mHasConnectedWifiManager = true;
+                }
+                mWifiManager.disableNetwork(networkId, WifiConfiguration.DISABLED_DNS_FAILURE);
+                if (mShowDisabledNotification && mConnectionInfo.isExplicitConnect()) {
+                    displayDisabledNetworkNotification(mConnectionInfo.getSSID());
                 }
                 transitionTo(mNotConnectedState);
             } else {
-                Slog.i(WWSM_TAG, "Blacklisting current BSSID.  " + wifiInfoToStr(mInitialConnInfo)
+                Slog.i(WWSM_TAG, "Blacklisting current BSSID.  " + wifiInfoToStr(mConnectionInfo)
                        + "numCheckFailures " + mNumCheckFailures + ", numAPs " + mBssids.size());
 
-                mWifiManager.addToBlacklist(mInitialConnInfo.getBSSID());
+                mWifiManager.addToBlacklist(mConnectionInfo.getBSSID());
                 mWifiManager.reassociate();
                 transitionTo(mBlacklistedApState);
             }