Merge "Removing logs of text that is being spoken."
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3cead11..c0714e3 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -42,6 +42,9 @@
 import android.database.sqlite.SQLiteDebug.DbStats;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.net.IConnectivityManager;
+import android.net.Proxy;
+import android.net.ProxyProperties;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Debug;
@@ -272,7 +275,7 @@
             super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky, token);
             this.intent = intent;
         }
-        
+
         Intent intent;
         ActivityInfo info;
         public String toString() {
@@ -592,6 +595,10 @@
             InetAddress.clearDnsCache();
         }
 
+        public void setHttpProxy(String host, String port, String exclList) {
+            Proxy.setHttpProxySystemProperty(host, port, exclList);
+        }
+
         public void processInBackground() {
             mH.removeMessages(H.GC_WHEN_IDLE);
             mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE));
@@ -3253,6 +3260,16 @@
             }
         }
 
+        /**
+         * Initialize the default http proxy in this process for the reasons we set the time zone.
+         */
+        IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
+        IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
+        try {
+            ProxyProperties proxyProperties = service.getProxy();
+            Proxy.setHttpProxySystemProperty(proxyProperties);
+        } catch (RemoteException e) {}
+
         if (data.instrumentationName != null) {
             ContextImpl appContext = new ContextImpl();
             appContext.init(data.info, null, this);
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index b19fb59..801c3f9 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -276,7 +276,7 @@
             requestThumbnail(b);
             return true;
         }
-        
+
         case SCHEDULE_CONFIGURATION_CHANGED_TRANSACTION:
         {
             data.enforceInterface(IApplicationThread.descriptor);
@@ -297,12 +297,21 @@
             return true;
         }
 
+        case SET_HTTP_PROXY_TRANSACTION: {
+            data.enforceInterface(IApplicationThread.descriptor);
+            final String proxy = data.readString();
+            final String port = data.readString();
+            final String exclList = data.readString();
+            setHttpProxy(proxy, port, exclList);
+            return true;
+        }
+
         case PROCESS_IN_BACKGROUND_TRANSACTION: {
             data.enforceInterface(IApplicationThread.descriptor);
             processInBackground();
             return true;
         }
-        
+
         case DUMP_SERVICE_TRANSACTION: {
             data.enforceInterface(IApplicationThread.descriptor);
             ParcelFileDescriptor fd = data.readFileDescriptor();
@@ -758,6 +767,16 @@
         data.recycle();
     }
 
+    public void setHttpProxy(String proxy, String port, String exclList) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        data.writeInterfaceToken(IApplicationThread.descriptor);
+        data.writeString(proxy);
+        data.writeString(port);
+        data.writeString(exclList);
+        mRemote.transact(SET_HTTP_PROXY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
+        data.recycle();
+    }
+
     public void processInBackground() throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 830c702..eca84ef 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -88,6 +88,7 @@
     void scheduleConfigurationChanged(Configuration config) throws RemoteException;
     void updateTimeZone() throws RemoteException;
     void clearDnsCache() throws RemoteException;
+    void setHttpProxy(String proxy, String port, String exclList) throws RemoteException;
     void processInBackground() throws RemoteException;
     void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args)
             throws RemoteException;
@@ -148,4 +149,5 @@
     int DUMP_HEAP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+35;
     int DUMP_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+36;
     int CLEAR_DNS_CACHE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+37;
+    int SET_HTTP_PROXY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+38;
 }
diff --git a/core/java/android/content/res/StringBlock.java b/core/java/android/content/res/StringBlock.java
index 5e90b91..23a6f97 100644
--- a/core/java/android/content/res/StringBlock.java
+++ b/core/java/android/content/res/StringBlock.java
@@ -87,21 +87,48 @@
             if (style != null) {
                 if (mStyleIDs == null) {
                     mStyleIDs = new StyleIDs();
-                    mStyleIDs.boldId = nativeIndexOfString(mNative, "b");
-                    mStyleIDs.italicId = nativeIndexOfString(mNative, "i");
-                    mStyleIDs.underlineId = nativeIndexOfString(mNative, "u");
-                    mStyleIDs.ttId = nativeIndexOfString(mNative, "tt");
-                    mStyleIDs.bigId = nativeIndexOfString(mNative, "big");
-                    mStyleIDs.smallId = nativeIndexOfString(mNative, "small");
-                    mStyleIDs.supId = nativeIndexOfString(mNative, "sup");
-                    mStyleIDs.subId = nativeIndexOfString(mNative, "sub");
-                    mStyleIDs.strikeId = nativeIndexOfString(mNative, "strike");
-                    mStyleIDs.listItemId = nativeIndexOfString(mNative, "li");
-                    mStyleIDs.marqueeId = nativeIndexOfString(mNative, "marquee");
+                }
 
-                    if (localLOGV) Log.v(TAG, "BoldId=" + mStyleIDs.boldId
-                            + ", ItalicId=" + mStyleIDs.italicId
-                            + ", UnderlineId=" + mStyleIDs.underlineId);
+                // the style array is a flat array of <type, start, end> hence
+                // the magic constant 3.
+                for (int styleIndex = 0; styleIndex < style.length; styleIndex += 3) {
+                    int styleId = style[styleIndex];
+
+                    if (styleId == mStyleIDs.boldId || styleId == mStyleIDs.italicId
+                            || styleId == mStyleIDs.underlineId || styleId == mStyleIDs.ttId
+                            || styleId == mStyleIDs.bigId || styleId == mStyleIDs.smallId
+                            || styleId == mStyleIDs.subId || styleId == mStyleIDs.supId
+                            || styleId == mStyleIDs.strikeId || styleId == mStyleIDs.listItemId
+                            || styleId == mStyleIDs.marqueeId) {
+                        // id already found skip to next style
+                        continue;
+                    }
+
+                    String styleTag = nativeGetString(mNative, styleId);
+
+                    if (styleTag.equals("b")) {
+                        mStyleIDs.boldId = styleId;
+                    } else if (styleTag.equals("i")) {
+                        mStyleIDs.italicId = styleId;
+                    } else if (styleTag.equals("u")) {
+                        mStyleIDs.underlineId = styleId;
+                    } else if (styleTag.equals("tt")) {
+                        mStyleIDs.ttId = styleId;
+                    } else if (styleTag.equals("big")) {
+                        mStyleIDs.bigId = styleId;
+                    } else if (styleTag.equals("small")) {
+                        mStyleIDs.smallId = styleId;
+                    } else if (styleTag.equals("sup")) {
+                        mStyleIDs.supId = styleId;
+                    } else if (styleTag.equals("sub")) {
+                        mStyleIDs.subId = styleId;
+                    } else if (styleTag.equals("strike")) {
+                        mStyleIDs.strikeId = styleId;
+                    } else if (styleTag.equals("li")) {
+                        mStyleIDs.listItemId = styleId;
+                    } else if (styleTag.equals("marquee")) {
+                        mStyleIDs.marqueeId = styleId;
+                    }
                 }
 
                 res = applyStyles(str, style, mStyleIDs);
@@ -119,17 +146,17 @@
     }
 
     static final class StyleIDs {
-        private int boldId;
-        private int italicId;
-        private int underlineId;
-        private int ttId;
-        private int bigId;
-        private int smallId;
-        private int subId;
-        private int supId;
-        private int strikeId;
-        private int listItemId;
-        private int marqueeId;
+        private int boldId = -1;
+        private int italicId = -1;
+        private int underlineId = -1;
+        private int ttId = -1;
+        private int bigId = -1;
+        private int smallId = -1;
+        private int subId = -1;
+        private int supId = -1;
+        private int strikeId = -1;
+        private int listItemId = -1;
+        private int marqueeId = -1;
     }
 
     private CharSequence applyStyles(String str, int[] style, StyleIDs ids) {
@@ -403,6 +430,5 @@
     private static final native int nativeGetSize(int obj);
     private static final native String nativeGetString(int obj, int idx);
     private static final native int[] nativeGetStyle(int obj, int idx);
-    private static final native int nativeIndexOfString(int obj, String str);
     private static final native void nativeDestroy(int obj);
 }
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index dd9c8f0..ecfa2c1 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -624,4 +624,39 @@
         } catch (RemoteException e) {
         }
     }
+
+    /**
+     * @param proxyProperties The definition for the new global http proxy
+     * {@hide}
+     */
+    public void setGlobalProxy(ProxyProperties p) {
+        try {
+            mService.setGlobalProxy(p);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * @return proxyProperties for the current global proxy
+     * {@hide}
+     */
+    public ProxyProperties getGlobalProxy() {
+        try {
+            return mService.getGlobalProxy();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
+     * @return proxyProperties for the current proxy (global if set, network specific if not)
+     * {@hide}
+     */
+    public ProxyProperties getProxy() {
+        try {
+            return mService.getProxy();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
 }
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 35054d6..70ab4f1 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -18,6 +18,7 @@
 
 import android.net.LinkProperties;
 import android.net.NetworkInfo;
+import android.net.ProxyProperties;
 import android.os.IBinder;
 
 /**
@@ -85,4 +86,10 @@
     void requestNetworkTransitionWakelock(in String forWhom);
 
     void reportInetCondition(int networkType, int percentage);
+
+    ProxyProperties getGlobalProxy();
+
+    void setGlobalProxy(in ProxyProperties p);
+
+    ProxyProperties getProxy();
 }
diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java
index 21c485e..3b9b9fe 100644
--- a/core/java/android/net/Proxy.java
+++ b/core/java/android/net/Proxy.java
@@ -16,9 +16,12 @@
 
 package android.net;
 
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
+import android.net.ProxyProperties;
 import android.os.Handler;
 import android.os.SystemProperties;
 import android.text.TextUtils;
@@ -55,17 +58,22 @@
 
     // Set to true to enable extra debugging.
     private static final boolean DEBUG = false;
+    private static final String TAG = "Proxy";
 
-    // Used to notify an app that's caching the default connection proxy
-    // that either the default connection or its proxy has changed
-    public static final String PROXY_CHANGE_ACTION =
-        "android.intent.action.PROXY_CHANGE";
-
-    private static ReadWriteLock sProxyInfoLock = new ReentrantReadWriteLock();
-
-    private static SettingsObserver sGlobalProxyChangedObserver = null;
-
-    private static ProxySpec sGlobalProxySpec = null;
+    /**
+     * Used to notify an app that's caching the default connection proxy
+     * that either the default connection or its proxy has changed.
+     * The intent will have the following extra value:</p>
+     * <ul>
+     *   <li><em>EXTRA_PROXY_INFO</em> - The ProxyProperties for the proxy
+     * </ul>
+     *
+     * <p class="note">This is a protected intent that can only be sent by the system
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE";
+    /** {@hide} **/
+    public static final String EXTRA_PROXY_INFO = "proxy";
 
     private static ConnectivityManager sConnectivityManager = null;
 
@@ -88,62 +96,6 @@
         EXCLLIST_PATTERN = Pattern.compile(EXCLLIST_REGEXP);
     }
 
-    // useful because it holds the processed exclusion list - don't want to reparse it each time
-    private static class ProxySpec {
-        String[] exclusionList;
-        InetSocketAddress address = null;
-        public ProxySpec() {
-            exclusionList = new String[0];
-        };
-    }
-
-    private static boolean isURLInExclusionList(String url, String[] exclusionList) {
-        if (url == null) {
-            return false;
-        }
-        Uri u = Uri.parse(url);
-        String urlDomain = u.getHost();
-        // If the domain is defined as ".android.com" or "android.com", we wish to match
-        // http://android.com as well as http://xxx.android.com , but not
-        // http://myandroid.com . This code works out the logic.
-        for (String excludedDomain : exclusionList) {
-            String dotDomain = "." + excludedDomain;
-            if (urlDomain.equals(excludedDomain)) {
-                return true;
-            }
-            if (urlDomain.endsWith(dotDomain)) {
-                return true;
-            }
-        }
-        // No match
-        return false;
-    }
-
-    private static String parseHost(String proxySpec) {
-        int i = proxySpec.indexOf(':');
-        if (i == -1) {
-            if (DEBUG) {
-                Assert.assertTrue(proxySpec.length() == 0);
-            }
-            return null;
-        }
-        return proxySpec.substring(0, i);
-    }
-
-    private static int parsePort(String proxySpec) {
-        int i = proxySpec.indexOf(':');
-        if (i == -1) {
-            if (DEBUG) {
-                Assert.assertTrue(proxySpec.length() == 0);
-            }
-            return -1;
-        }
-        if (DEBUG) {
-            Assert.assertTrue(i < proxySpec.length());
-        }
-        return Integer.parseInt(proxySpec.substring(i+1));
-    }
-
     /**
      * Return the proxy object to be used for the URL given as parameter.
      * @param ctx A Context used to get the settings for the proxy host.
@@ -154,34 +106,31 @@
      * {@hide}
      */
     public static final java.net.Proxy getProxy(Context ctx, String url) {
-        sProxyInfoLock.readLock().lock();
-        java.net.Proxy retval;
-        try {
-            if (sGlobalProxyChangedObserver == null) {
-                registerContentObserversReadLocked(ctx);
-                parseGlobalProxyInfoReadLocked(ctx);
+        String host = "";
+        if (url != null) {
+            URI uri = URI.create(url);
+            host = uri.getHost();
+        }
+
+        if (!isLocalHost(host)) {
+            if (sConnectivityManager == null) {
+                sConnectivityManager = (ConnectivityManager)ctx.getSystemService(
+                        Context.CONNECTIVITY_SERVICE);
             }
-            if (sGlobalProxySpec != null) {
-                // Proxy defined - Apply exclusion rules
-                if (isURLInExclusionList(url, sGlobalProxySpec.exclusionList)) {
-                    // Return no proxy
-                    retval = java.net.Proxy.NO_PROXY;
-                } else {
-                    retval =
-                        new java.net.Proxy(java.net.Proxy.Type.HTTP, sGlobalProxySpec.address);
+            if (sConnectivityManager == null) return java.net.Proxy.NO_PROXY;
+
+            ProxyProperties proxyProperties = sConnectivityManager.getProxy();
+
+            if (proxyProperties != null) {
+                if (!proxyProperties.isExcluded(host)) {
+                    return proxyProperties.makeProxy();
                 }
-            } else {
-                retval = getDefaultProxy(ctx, url);
             }
-        } finally {
-            sProxyInfoLock.readLock().unlock();
         }
-        if ((retval != java.net.Proxy.NO_PROXY) && (isLocalHost(url))) {
-            retval = java.net.Proxy.NO_PROXY;
-        }
-        return retval;
+        return java.net.Proxy.NO_PROXY;
     }
 
+
     // TODO: deprecate this function
     /**
      * Return the proxy host set by the user.
@@ -236,35 +185,6 @@
         return -1;
     }
 
-    // TODO - cache the details for each network so we don't have to fetch and parse
-    // on each request
-    private static final java.net.Proxy getDefaultProxy(Context context, String url) {
-        if (sConnectivityManager == null) {
-            sConnectivityManager = (ConnectivityManager)context.getSystemService(
-                    Context.CONNECTIVITY_SERVICE);
-        }
-        if (sConnectivityManager == null) return java.net.Proxy.NO_PROXY;
-
-        LinkProperties linkProperties = sConnectivityManager.getActiveLinkProperties();
-
-        if (linkProperties != null) {
-            ProxyProperties proxyProperties = linkProperties.getHttpProxy();
-
-            if (proxyProperties != null) {
-                String exclusionList = proxyProperties.getExclusionList();
-                SocketAddress socketAddr = proxyProperties.getSocketAddress();
-                if (socketAddr != null) {
-                    String[] parsedExclusionArray =
-                            parsedExclusionArray = parseExclusionList(exclusionList);
-                    if (!isURLInExclusionList(url, parsedExclusionArray)) {
-                        return new java.net.Proxy(java.net.Proxy.Type.HTTP, socketAddr);
-                    }
-                }
-            }
-        }
-        return java.net.Proxy.NO_PROXY;
-    }
-
     // TODO: remove this function / deprecate
     /**
      * Returns the preferred proxy to be used by clients. This is a wrapper
@@ -291,13 +211,11 @@
         }
     }
 
-    private static final boolean isLocalHost(String url) {
-        if (url == null) {
+    private static final boolean isLocalHost(String host) {
+        if (host == null) {
             return false;
         }
         try {
-            final URI uri = URI.create(url);
-            final String host = uri.getHost();
             if (host != null) {
                 if (host.equalsIgnoreCase("localhost")) {
                     return true;
@@ -317,92 +235,6 @@
         return false;
     }
 
-    private static class SettingsObserver extends ContentObserver {
-
-        private Context mContext;
-
-        SettingsObserver(Context ctx) {
-            super(new Handler(ctx.getMainLooper()));
-            mContext = ctx;
-        }
-
-        @Override
-        public void onChange(boolean selfChange) {
-            sProxyInfoLock.readLock().lock();
-            parseGlobalProxyInfoReadLocked(mContext);
-            sProxyInfoLock.readLock().unlock();
-        }
-    }
-
-    private static final void registerContentObserversReadLocked(Context ctx) {
-        Uri uriGlobalProxy = Settings.Secure.getUriFor(Settings.Secure.HTTP_PROXY);
-        Uri uriGlobalExclList =
-            Settings.Secure.getUriFor(Settings.Secure.HTTP_PROXY_EXCLUSION_LIST);
-
-        // No lock upgrading (from read to write) allowed
-        sProxyInfoLock.readLock().unlock();
-        sProxyInfoLock.writeLock().lock();
-        try {
-            sGlobalProxyChangedObserver = new SettingsObserver(ctx);
-        } finally {
-            // Downgrading locks (from write to read) is allowed
-            sProxyInfoLock.readLock().lock();
-            sProxyInfoLock.writeLock().unlock();
-        }
-        ctx.getContentResolver().registerContentObserver(uriGlobalProxy, false,
-                sGlobalProxyChangedObserver);
-        ctx.getContentResolver().registerContentObserver(uriGlobalExclList, false,
-                sGlobalProxyChangedObserver);
-    }
-
-    private static final void parseGlobalProxyInfoReadLocked(Context ctx) {
-        ContentResolver contentResolver = ctx.getContentResolver();
-        String proxyHost =  Settings.Secure.getString(
-                contentResolver,
-                Settings.Secure.HTTP_PROXY);
-        if (TextUtils.isEmpty(proxyHost)) {
-            // Clear signal
-            sProxyInfoLock.readLock().unlock();
-            sProxyInfoLock.writeLock().lock();
-            sGlobalProxySpec = null;
-            sProxyInfoLock.readLock().lock();
-            sProxyInfoLock.writeLock().unlock();
-            return;
-        }
-        String exclusionListSpec = Settings.Secure.getString(
-                contentResolver,
-                Settings.Secure.HTTP_PROXY_EXCLUSION_LIST);
-        String host = parseHost(proxyHost);
-        int port = parsePort(proxyHost);
-        ProxySpec tmpProxySpec = null;
-        if (proxyHost != null) {
-            tmpProxySpec = new ProxySpec();
-            tmpProxySpec.address = new InetSocketAddress(host, port);
-            tmpProxySpec.exclusionList = parseExclusionList(exclusionListSpec);
-        }
-        sProxyInfoLock.readLock().unlock();
-        sProxyInfoLock.writeLock().lock();
-        sGlobalProxySpec = tmpProxySpec;
-        sProxyInfoLock.readLock().lock();
-        sProxyInfoLock.writeLock().unlock();
-    }
-
-    private static String[] parseExclusionList(String exclusionList) {
-        String[] processedArray = new String[0];
-        if (!TextUtils.isEmpty(exclusionList)) {
-            String[] exclusionListArray = exclusionList.toLowerCase().split(",");
-            processedArray = new String[exclusionListArray.length];
-            for (int i = 0; i < exclusionListArray.length; i++) {
-                String entry = exclusionListArray[i].trim();
-                if (entry.startsWith(".")) {
-                    entry = entry.substring(1);
-                }
-                processedArray[i] = entry;
-            }
-        }
-        return processedArray;
-    }
-
     /**
      * Validate syntax of hostname, port and exclusion list entries
      * {@hide}
@@ -480,4 +312,44 @@
                 new SchemeRegistry(), ProxySelector.getDefault(), context);
         return ret;
     }
+
+    /** @hide */
+    public static final void setHttpProxySystemProperty(ProxyProperties p) {
+        String host = null;
+        String port = null;
+        String exclList = null;
+        if (p != null) {
+            host = p.getHost();
+            port = Integer.toString(p.getPort());
+            exclList = p.getExclusionList();
+        }
+        setHttpProxySystemProperty(host, port, exclList);
+    }
+
+    /** @hide */
+    public static final void setHttpProxySystemProperty(String host, String port, String exclList) {
+        if (exclList != null) exclList = exclList.replace(",", "|");
+        if (false) Log.d(TAG, "setHttpProxySystemProperty :"+host+":"+port+" - "+exclList);
+        if (host != null) {
+            System.setProperty("http.proxyHost", host);
+            System.setProperty("https.proxyHost", host);
+        } else {
+            System.clearProperty("http.proxyHost");
+            System.clearProperty("https.proxyHost");
+        }
+        if (port != null) {
+            System.setProperty("http.proxyPort", port);
+            System.setProperty("https.proxyPort", port);
+        } else {
+            System.clearProperty("http.proxyPort");
+            System.clearProperty("https.proxyPort");
+        }
+        if (exclList != null) {
+            System.setProperty("http.nonProxyHosts", exclList);
+            System.setProperty("https.nonProxyHosts", exclList);
+        } else {
+            System.clearProperty("http.nonProxyHosts");
+            System.clearProperty("https.nonProxyHosts");
+        }
+    }
 }
diff --git a/core/java/android/net/ProxyProperties.aidl b/core/java/android/net/ProxyProperties.aidl
new file mode 100644
index 0000000..02ea15d
--- /dev/null
+++ b/core/java/android/net/ProxyProperties.aidl
@@ -0,0 +1,21 @@
+/*
+**
+** 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 android.net;
+
+parcelable ProxyProperties;
+
diff --git a/core/java/android/net/ProxyProperties.java b/core/java/android/net/ProxyProperties.java
index 5fd0d89..cbe4445 100644
--- a/core/java/android/net/ProxyProperties.java
+++ b/core/java/android/net/ProxyProperties.java
@@ -19,6 +19,8 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.Log;
 
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
@@ -30,44 +32,108 @@
  */
 public class ProxyProperties implements Parcelable {
 
-    private InetSocketAddress mProxy;
+    private String mHost;
+    private int mPort;
     private String mExclusionList;
+    private String[] mParsedExclusionList;
 
-    public ProxyProperties() {
+    public ProxyProperties(String host, int port, String exclList) {
+        mHost = host;
+        mPort = port;
+        setExclusionList(exclList);
+    }
+
+    private ProxyProperties(String host, int port, String exclList, String[] parsedExclList) {
+        mHost = host;
+        mPort = port;
+        mExclusionList = exclList;
+        mParsedExclusionList = parsedExclList;
     }
 
     // copy constructor instead of clone
     public ProxyProperties(ProxyProperties source) {
         if (source != null) {
-            mProxy = source.getSocketAddress();
-            String exclusionList = source.getExclusionList();
-            if (exclusionList != null) {
-                mExclusionList = new String(exclusionList);
-            }
+            mHost = source.getHost();
+            mPort = source.getPort();
+            mExclusionList = source.getExclusionList();
+            mParsedExclusionList = source.mParsedExclusionList;
         }
     }
 
     public InetSocketAddress getSocketAddress() {
-        return mProxy;
+        InetSocketAddress inetSocketAddress = null;
+        try {
+            inetSocketAddress = new InetSocketAddress(mHost, mPort);
+        } catch (IllegalArgumentException e) { }
+        return inetSocketAddress;
     }
 
-    public void setSocketAddress(InetSocketAddress proxy) {
-        mProxy = proxy;
+    public String getHost() {
+        return mHost;
     }
 
+    public int getPort() {
+        return mPort;
+    }
+
+    // comma separated
     public String getExclusionList() {
         return mExclusionList;
     }
 
-    public void setExclusionList(String exclusionList) {
+    // comma separated
+    private void setExclusionList(String exclusionList) {
         mExclusionList = exclusionList;
+        if (mExclusionList == null) {
+            mParsedExclusionList = new String[0];
+        } else {
+            String splitExclusionList[] = exclusionList.toLowerCase().split(",");
+            mParsedExclusionList = new String[splitExclusionList.length * 2];
+            for (int i = 0; i < splitExclusionList.length; i++) {
+                String s = splitExclusionList[i].trim();
+                if (s.startsWith(".")) s = s.substring(1);
+                mParsedExclusionList[i*2] = s;
+                mParsedExclusionList[(i*2)+1] = "." + s;
+            }
+        }
+    }
+
+    public boolean isExcluded(String url) {
+        if (TextUtils.isEmpty(url) || mParsedExclusionList == null ||
+                mParsedExclusionList.length == 0) return false;
+
+        Uri u = Uri.parse(url);
+        String urlDomain = u.getHost();
+        if (urlDomain == null) return false;
+        for (int i = 0; i< mParsedExclusionList.length; i+=2) {
+            if (urlDomain.equals(mParsedExclusionList[i]) ||
+                    urlDomain.endsWith(mParsedExclusionList[i+1])) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public java.net.Proxy makeProxy() {
+        java.net.Proxy proxy = java.net.Proxy.NO_PROXY;
+        if (mHost != null) {
+            try {
+                InetSocketAddress inetSocketAddress = new InetSocketAddress(mHost, mPort);
+                proxy = new java.net.Proxy(java.net.Proxy.Type.HTTP, inetSocketAddress);
+            } catch (IllegalArgumentException e) {
+            }
+        }
+        return proxy;
     }
 
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
-        if (mProxy != null) {
-            sb.append(mProxy.toString());
+        if (mHost != null) {
+            sb.append("[");
+            sb.append(mHost);
+            sb.append("] ");
+            sb.append(Integer.toString(mPort));
             if (mExclusionList != null) {
                     sb.append(" xl=").append(mExclusionList);
             }
@@ -75,6 +141,20 @@
         return sb.toString();
     }
 
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof ProxyProperties)) return false;
+        ProxyProperties p = (ProxyProperties)o;
+        if (mExclusionList != null && !mExclusionList.equals(p.getExclusionList())) return false;
+        if (mHost != null && p.getHost() != null && mHost.equals(p.getHost()) == false) {
+            return false;
+        }
+        if (mHost != null && p.mHost == null) return false;
+        if (mHost == null && p.mHost != null) return false;
+        if (mPort != p.mPort) return false;
+        return true;
+    }
+
     /**
      * Implement the Parcelable interface
      * @hide
@@ -88,27 +168,15 @@
      * @hide
      */
     public void writeToParcel(Parcel dest, int flags) {
-        String host = null;
-        if (mProxy != null) {
-            try {
-                InetAddress addr = mProxy.getAddress();
-                if (addr != null) {
-                    host = addr.getHostAddress();
-                } else {
-                    /* Does not resolve when addr is null */
-                    host = mProxy.getHostName();
-                }
-            } catch (Exception e) { }
-        }
-
-        if (host != null) {
+        if (mHost != null) {
             dest.writeByte((byte)1);
-            dest.writeString(host);
-            dest.writeInt(mProxy.getPort());
+            dest.writeString(mHost);
+            dest.writeInt(mPort);
         } else {
             dest.writeByte((byte)0);
         }
         dest.writeString(mExclusionList);
+        dest.writeStringArray(mParsedExclusionList);
     }
 
     /**
@@ -118,16 +186,16 @@
     public static final Creator<ProxyProperties> CREATOR =
         new Creator<ProxyProperties>() {
             public ProxyProperties createFromParcel(Parcel in) {
-                ProxyProperties proxyProperties = new ProxyProperties();
+                String host = null;
+                int port = 0;
                 if (in.readByte() == 1) {
-                    try {
-                        String host = in.readString();
-                        int port = in.readInt();
-                        proxyProperties.setSocketAddress(InetSocketAddress.createUnresolved(
-                                host, port));
-                    } catch (IllegalArgumentException e) { }
+                    host = in.readString();
+                    port = in.readInt();
                 }
-                proxyProperties.setExclusionList(in.readString());
+                String exclList = in.readString();
+                String[] parsedExclList = in.readStringArray();
+                ProxyProperties proxyProperties =
+                        new ProxyProperties(host, port, exclList, parsedExclList);
                 return proxyProperties;
             }
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1fe2c5a..7075774 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2424,17 +2424,32 @@
         public static final String DISABLED_SYSTEM_INPUT_METHODS = "disabled_system_input_methods";
 
         /**
-         * Host name and port for global proxy.
+         * Host name and port for global http proxy.  Uses ':' seperator for between host and port
+         * TODO - deprecate in favor of global_http_proxy_host, etc
          */
         public static final String HTTP_PROXY = "http_proxy";
 
         /**
+         * Host name for global http proxy.  Set via ConnectivityManager.
+         * @hide
+         */
+        public static final String GLOBAL_HTTP_PROXY_HOST = "global_http_proxy_host";
+
+        /**
+         * Integer host port for global http proxy.  Set via ConnectivityManager.
+         * @hide
+         */
+        public static final String GLOBAL_HTTP_PROXY_PORT = "global_http_proxy_port";
+
+        /**
          * Exclusion list for global proxy. This string contains a list of comma-separated
          * domains where the global proxy does not apply. Domains should be listed in a comma-
          * separated list. Example of acceptable formats: ".domain1.com,my.domain2.com"
+         * Use ConnectivityManager to set/get.
          * @hide
          */
-        public static final String HTTP_PROXY_EXCLUSION_LIST = "http_proxy_exclusion_list";
+        public static final String GLOBAL_HTTP_PROXY_EXCLUSION_LIST =
+                "global_http_proxy_exclusion_list";
 
         /**
          * Enables the UI setting to allow the user to specify the global HTTP proxy
diff --git a/core/jni/android_util_StringBlock.cpp b/core/jni/android_util_StringBlock.cpp
index 641fbce..a021efd 100644
--- a/core/jni/android_util_StringBlock.cpp
+++ b/core/jni/android_util_StringBlock.cpp
@@ -147,25 +147,6 @@
     return array;
 }
 
-static jint android_content_StringBlock_nativeIndexOfString(JNIEnv* env, jobject clazz,
-                                                         jint token, jstring str)
-{
-    ResStringPool* osb = (ResStringPool*)token;
-    if (osb == NULL || str == NULL) {
-        doThrow(env, "java/lang/NullPointerException");
-        return 0;
-    }
-
-    const char16_t* str16 = env->GetStringChars(str, NULL);
-    jsize strLen = env->GetStringLength(str);
-
-    ssize_t idx = osb->indexOfString(str16, strLen);
-
-    env->ReleaseStringChars(str, str16);
-
-    return idx;
-}
-
 static void android_content_StringBlock_nativeDestroy(JNIEnv* env, jobject clazz,
                                                    jint token)
 {
@@ -193,8 +174,6 @@
             (void*) android_content_StringBlock_nativeGetString },
     { "nativeGetStyle",    "(II)[I",
             (void*) android_content_StringBlock_nativeGetStyle },
-    { "nativeIndexOfString","(ILjava/lang/String;)I",
-            (void*) android_content_StringBlock_nativeIndexOfString },
     { "nativeDestroy",      "(I)V",
             (void*) android_content_StringBlock_nativeDestroy },
 };
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d02ca64..ddc63dd 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -92,6 +92,7 @@
     <protected-broadcast android:name="android.nfc.action.LLCP_LINK_STATE_CHANGED" />
     <protected-broadcast android:name="android.nfc.action.TRANSACTION_DETECTED" />
     <protected-broadcast android:name="android.intent.action.CLEAR_DNS_CACHE" />
+    <protected-broadcast android:name="android.intent.action.PROXY_CHANGE" />
 
     <!-- ====================================== -->
     <!-- Permissions for things that cost money -->
diff --git a/docs/html/resources/resources-data.js b/docs/html/resources/resources-data.js
index d06b695..221406c 100644
--- a/docs/html/resources/resources-data.js
+++ b/docs/html/resources/resources-data.js
@@ -465,7 +465,7 @@
     }
   },
   {
-    tags: ['sample', 'ui', 'search', 'new'],
+    tags: ['sample', 'ui', 'search'],
     path: 'samples/SearchableDictionary/index.html',
     title: {
       en: 'Searchable Dictionary v2'
@@ -485,7 +485,7 @@
     }
   },
   {
-    tags: ['sample', 'testing', 'new'],
+    tags: ['sample', 'testing'],
     path: 'samples/Spinner/index.html',
     title: {
       en: 'Spinner'
@@ -495,7 +495,7 @@
     }
   },
   {
-    tags: ['sample', 'testing', 'new'],
+    tags: ['sample', 'testing'],
     path: 'samples/SpinnerTest/index.html',
     title: {
       en: 'SpinnerTest'
@@ -505,7 +505,7 @@
     }
   },
   {
-    tags: ['sample', 'newfeature', 'new'],
+    tags: ['sample', 'newfeature'],
     path: 'samples/TicTacToeLib/index.html',
     title: {
       en: 'TicTacToeLib'
@@ -515,7 +515,7 @@
     }
   },
   {
-    tags: ['sample', 'newfeature', 'new'],
+    tags: ['sample', 'newfeature',],
     path: 'samples/TicTacToeMain/index.html',
     title: {
       en: 'TicTacToeMain'
@@ -610,7 +610,7 @@
     }
   },
   {
-    tags: ['tutorial', 'testing', 'new'],
+    tags: ['tutorial', 'testing'],
     path: 'tutorials/testing/helloandroid_test.html',
     title: {
       en: 'Hello Testing'
@@ -620,7 +620,7 @@
     }
   },
   {
-    tags: ['tutorial', 'testing', 'new'],
+    tags: ['tutorial', 'testing'],
     path: 'tutorials/testing/activity_test.html',
     title: {
       en: 'Activity Testing'
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 7f765ca..829ab20 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -465,7 +465,7 @@
         return OK;
     }
 
-    LOGI("new range: offset= %ld", offset);
+    LOGI("new range: offset= %lld", offset);
 
     mCacheOffset = offset;
 
diff --git a/media/tests/mtp/Android.mk b/media/tests/mtp/Android.mk
deleted file mode 100644
index a9074ed..0000000
--- a/media/tests/mtp/Android.mk
+++ /dev/null
@@ -1,61 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-ifneq ($(TARGET_SIMULATOR),true)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-	mtp.cpp \
-	MtpFile.cpp \
-
-LOCAL_C_INCLUDES += \
-    frameworks/base/media/mtp \
-
-LOCAL_CFLAGS := -DMTP_HOST
-
-LOCAL_MODULE := mtp
-
-LOCAL_STATIC_LIBRARIES := libmtp libusbhost libutils libcutils
-
-include $(BUILD_EXECUTABLE)
-
-endif
-
-ifeq ($(HOST_OS),linux)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-	mtp.cpp \
-	MtpFile.cpp \
-	../../../libs/utils/RefBase.cpp \
-	../../../libs/utils/SharedBuffer.cpp \
-	../../../libs/utils/Threads.cpp \
-	../../../libs/utils/VectorImpl.cpp \
-
-LOCAL_C_INCLUDES += \
-    frameworks/base/media/mtp \
-
-LOCAL_CFLAGS := -DMTP_HOST -g -O0
-
-have_readline := $(wildcard /usr/include/readline/readline.h)
-have_history := $(wildcard /usr/lib/libhistory*)
-ifneq ($(strip $(have_readline)),)
-LOCAL_CFLAGS += -DHAVE_READLINE=1
-endif
-
-LOCAL_LDLIBS += -lpthread
-ifneq ($(strip $(have_readline)),)
-LOCAL_LDLIBS += -lreadline -lncurses
-endif
-ifneq ($(strip $(have_history)),)
-LOCAL_LDLIBS += -lhistory
-endif
-
-LOCAL_MODULE := mtp
-
-LOCAL_STATIC_LIBRARIES := libmtp libusbhost libcutils
-
-include $(BUILD_HOST_EXECUTABLE)
-
-endif
diff --git a/media/tests/mtp/MtpFile.cpp b/media/tests/mtp/MtpFile.cpp
deleted file mode 100644
index 00d328e..0000000
--- a/media/tests/mtp/MtpFile.cpp
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * 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.
- */
-
-#include "MtpClient.h"
-#include "MtpDevice.h"
-#include "MtpDeviceInfo.h"
-#include "MtpObjectInfo.h"
-#include "MtpStorage.h"
-#include "MtpUtils.h"
-
-#include "MtpFile.h"
-
-namespace android {
-
-MtpClient* MtpFile::sClient = NULL;
-
-MtpFile::MtpFile(MtpDevice* device)
-    :   mDevice(device),
-        mStorage(0),
-        mHandle(0)
-{
-}
-
-MtpFile::MtpFile(MtpDevice* device, MtpStorageID storage)
-    :   mDevice(device),
-        mStorage(storage),
-        mHandle(0)
-{
-}
-
-MtpFile::MtpFile(MtpDevice* device, MtpStorageID storage, MtpObjectHandle handle)
-    :   mDevice(device),
-        mStorage(storage),
-        mHandle(handle)
-{
-}
-
-MtpFile::MtpFile(MtpFile* file)
-    :   mDevice(file->mDevice),
-        mStorage(file->mStorage),
-        mHandle(file->mHandle)
-{
-}
-
-MtpFile::~MtpFile() {
-}
-
-void MtpFile::print() {
-    if (mHandle) {
-
-    } else if (mStorage) {
-        printf("%x\n", mStorage);
-    } else {
-        int id = mDevice->getID();
-        MtpDeviceInfo* info = mDevice->getDeviceInfo();
-        if (info)
-            printf("%d\t%s %s %s\n", id, info->mManufacturer, info->mModel, info->mSerial);
-        else
-            printf("%d\t(no device info available)\n", id);
-        delete info;
-    }
-}
-
-MtpObjectInfo* MtpFile::getObjectInfo() {
-    return mDevice->getObjectInfo(mHandle);
-}
-
-void MtpFile::list() {
-    if (mStorage) {
-        MtpObjectHandleList* handles = mDevice->getObjectHandles(mStorage, 0,
-                                                (mHandle ? mHandle : -1));
-        if (handles) {
-            for (int i = 0; i < handles->size(); i++) {
-                MtpObjectHandle handle = (*handles)[i];
-                MtpObjectInfo* info = mDevice->getObjectInfo(handle);
-                if (info) {
-                    char modified[100];
-                    struct tm tm;
-
-                    gmtime_r(&info->mDateModified, &tm);
-                    strftime(modified, sizeof(modified), "%a %b %e %H:%M:%S GMT %Y", &tm);
-                    printf("%s Handle: %d Format: %04X Size: %d Modified: %s\n",
-                            info->mName, handle, info->mFormat, info->mCompressedSize, modified);
-                    delete info;
-                }
-            }
-            delete handles;
-        }
-    } else {
-        // list storage units for device
-        MtpStorageIDList* storageList = mDevice->getStorageIDs();
-        for (int i = 0; i < storageList->size(); i++) {
-            MtpStorageID storageID = (*storageList)[i];
-            printf("%x\n", storageID);
-        }
-    }
-}
-
-void MtpFile::init(MtpClient* client) {
-    sClient = client;
-}
-
-MtpFile* MtpFile::parsePath(MtpFile* base, char* path) {
-    MtpDevice* device = NULL;
-    MtpStorageID storage = 0;
-    MtpObjectHandle handle = 0;
-
-    if (path[0] != '/' && base) {
-        device = base->mDevice;
-        storage = base->mStorage;
-        handle = base->mHandle;
-    }
-
-    // parse an absolute path
-    if (path[0] == '/')
-        path++;
-    char* tok = strtok(path, "/");
-    while (tok) {
-        if (storage) {
-            // find child of current handle
-            MtpObjectHandleList* handles = device->getObjectHandles(storage, 0,
-                                                    (handle ? handle : -1));
-            MtpObjectHandle childHandle = 0;
-
-            if (handles) {
-                for (int i = 0; i < handles->size() && !childHandle; i++) {
-                    MtpObjectHandle handle = (*handles)[i];
-                    MtpObjectInfo* info = device->getObjectInfo(handle);
-                    if (info && !strcmp(tok, info->mName))
-                        childHandle = handle;
-                    delete info;
-                }
-                delete handles;
-            }
-            if (childHandle)
-                handle = childHandle;
-            else
-                return NULL;
-        } else if (device) {
-            unsigned int id;
-            // find storage for the device
-            if (sscanf(tok, "%x", &id) == 1) {
-                MtpStorageIDList* storageList = device->getStorageIDs();
-                bool found = false;
-                for (int i = 0; i < storageList->size(); i++) {
-                    if ((*storageList)[i] == id) {
-                        found = true;
-                        break;
-                    }
-                }
-                if (found)
-                    storage = id;
-                else
-                    return NULL;
-            }
-        } else {
-            // find device
-            unsigned int id;
-            if (sscanf(tok, "%d", &id) == 1)
-                device = sClient->getDevice(id);
-            if (!device)
-                return NULL;
-        }
-
-        tok = strtok(NULL, "/");
-    }
-
-    if (device)
-        return new MtpFile(device, storage, handle);
-    else
-        return NULL;
-}
-
-}
diff --git a/media/tests/mtp/MtpFile.h b/media/tests/mtp/MtpFile.h
deleted file mode 100644
index ab8762b..0000000
--- a/media/tests/mtp/MtpFile.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _MTP_FILE_H
-#define _MTP_FILE_H
-
-#include "MtpTypes.h"
-
-namespace android {
-
-class MtpClient;
-class MtpDevice;
-class MtpObjectInfo;
-
-// File-like abstraction for the interactive shell.
-// This can be used to represent an MTP device, storage unit or object
-// (either file or association).
-class MtpFile {
-private:
-    MtpDevice*          mDevice;
-    MtpStorageID        mStorage;
-    MtpObjectHandle     mHandle;
-    static MtpClient*   sClient;
-
-public:
-    MtpFile(MtpDevice* device);
-    MtpFile(MtpDevice* device, MtpStorageID storage);
-    MtpFile(MtpDevice* device, MtpStorageID storage, MtpObjectHandle handle);
-    MtpFile(MtpFile* file);
-    virtual ~MtpFile();
-
-    MtpObjectInfo* getObjectInfo();
-    void print();
-    void list();
-
-    inline MtpDevice* getDevice() const { return mDevice; }
-
-    static void init(MtpClient* client);
-    static MtpFile* parsePath(MtpFile* base, char* path);
-};
-
-}
-
-#endif // _MTP_DIRECTORY_H
diff --git a/media/tests/mtp/mtp.cpp b/media/tests/mtp/mtp.cpp
deleted file mode 100644
index 9732944..0000000
--- a/media/tests/mtp/mtp.cpp
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * 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.
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#if HAVE_READLINE
-#include <readline/readline.h>
-#include <readline/history.h>
-#endif
-
-#include "MtpClient.h"
-#include "MtpDevice.h"
-#include "MtpObjectInfo.h"
-
-#include "MtpFile.h"
-
-#define PROMPT  "mtp> "
-
-using namespace android;
-
-static MtpClient* sClient = NULL;
-
-// current working directory information for interactive shell
-static MtpFile* sCurrentDirectory = NULL;
-
-static MtpFile* parse_path(char* path) {
-    return MtpFile::parsePath(sCurrentDirectory, path);
-}
-
-class MyClient : public MtpClient {
-private:
-    virtual void deviceAdded(MtpDevice *device) {
-    }
-
-    virtual void deviceRemoved(MtpDevice *device) {
-    }
-
-public:
-};
-
-static void init() {
-    sClient = new MyClient;
-    sClient->start();
-    MtpFile::init(sClient);
-}
-
-static int set_cwd(int argc, char* argv[]) {
-    if (argc != 1) {
-        fprintf(stderr, "cd should have one argument\n");
-        return -1;
-    }
-    if (!strcmp(argv[0], "/")) {
-        delete sCurrentDirectory;
-        sCurrentDirectory = NULL;
-    }
-    else {
-        MtpFile* file = parse_path(argv[0]);
-        if (file) {
-            delete sCurrentDirectory;
-            sCurrentDirectory = file;
-        } else {
-            fprintf(stderr, "could not find %s\n", argv[0]);
-            return -1;
-        }
-    }
-    return 0;
-}
-
-static void list_devices() {
-    // TODO - need to make sure the list will not change while iterating
-    MtpDeviceList& devices = sClient->getDeviceList();
-    for (int i = 0; i < devices.size(); i++) {
-        MtpDevice* device = devices[i];
-        MtpFile* file = new MtpFile(device);
-        file->print();
-        delete file;
-    }
-}
-
-static int list(int argc, char* argv[]) {
-    if (argc == 0) {
-        // list cwd
-        if (sCurrentDirectory) {
-            sCurrentDirectory->list();
-        } else {
-            list_devices();
-        }
-    }
-
-    for (int i = 0; i < argc; i++) {
-        char* path = argv[i];
-        if (!strcmp(path, "/")) {
-            list_devices();
-        } else {
-            MtpFile* file = parse_path(path);
-            if (!file) {
-                fprintf(stderr, "could not find %s\n", path);
-                return -1;
-            }
-            file->list();
-        }
-    }
-
-    return 0;
-}
-
-static int get_file(int argc, char* argv[]) {
-    int ret = -1;
-    int srcFD = -1;
-    int destFD = -1;
-    MtpFile* srcFile = NULL;
-    MtpObjectInfo* info = NULL;
-    char* dest;
-
-    if (argc < 1) {
-        fprintf(stderr, "not enough arguments\n");
-        return -1;
-    } else if (argc > 2) {
-        fprintf(stderr, "too many arguments\n");
-        return -1;
-    }
-
-    // find source object
-    char* src = argv[0];
-    srcFile = parse_path(src);
-    if (!srcFile) {
-        fprintf(stderr, "could not find %s\n", src);
-        return -1;
-    }
-    info = srcFile->getObjectInfo();
-    if (!info) {
-        fprintf(stderr, "could not find object info for %s\n", src);
-        goto fail;
-    }
-    if (info->mFormat == MTP_FORMAT_ASSOCIATION) {
-        fprintf(stderr, "copying directories not implemented yet\n");
-        goto fail;
-    }
-
-    dest = (argc > 1 ? argv[1] : info->mName);
-    if (srcFile->getDevice()->readObject(info->mHandle, dest))
-        ret = 0;
-
-fail:
-    delete srcFile;
-    delete info;
-    return ret;
-}
-
-static int put_file(int argc, char* argv[]) {
-    int ret = -1;
-    int srcFD = -1;
-    MtpFile* destFile = NULL;
-    MtpObjectInfo* srcInfo = NULL;
-    MtpObjectInfo* destInfo = NULL;
-    MtpObjectHandle handle;
-    struct stat statbuf;
-    const char* lastSlash;
-
-    if (argc < 1) {
-        fprintf(stderr, "not enough arguments\n");
-        return -1;
-    } else if (argc > 2) {
-        fprintf(stderr, "too many arguments\n");
-        return -1;
-    }
-    const char* src = argv[0];
-    srcFD = open(src, O_RDONLY);
-    if (srcFD < 0) {
-        fprintf(stderr, "could not open %s\n", src);
-        goto fail;
-    }
-    if (argc == 2) {
-         char* dest = argv[1];
-        destFile = parse_path(dest);
-        if (!destFile) {
-            fprintf(stderr, "could not find %s\n", dest);
-            goto fail;
-        }
-    } else {
-        if (!sCurrentDirectory) {
-            fprintf(stderr, "current working directory not set\n");
-            goto fail;
-        }
-        destFile = new MtpFile(sCurrentDirectory);
-    }
-
-    destInfo = destFile->getObjectInfo();
-    if (!destInfo) {
-        fprintf(stderr, "could not find object info destination directory\n");
-        goto fail;
-    }
-    if (destInfo->mFormat != MTP_FORMAT_ASSOCIATION) {
-        fprintf(stderr, "destination not a directory\n");
-        goto fail;
-    }
-
-    if (fstat(srcFD, &statbuf))
-        goto fail;
-
-    srcInfo = new MtpObjectInfo(0);
-    srcInfo->mStorageID = destInfo->mStorageID;
-    srcInfo->mFormat = MTP_FORMAT_EXIF_JPEG;  // FIXME
-    srcInfo->mCompressedSize = statbuf.st_size;
-    srcInfo->mParent = destInfo->mHandle;
-    lastSlash = strrchr(src, '/');
-    srcInfo->mName = strdup(lastSlash ? lastSlash + 1 : src);
-    srcInfo->mDateModified = statbuf.st_mtime;
-    handle = destFile->getDevice()->sendObjectInfo(srcInfo);
-    if (handle <= 0) {
-        printf("sendObjectInfo returned %04X\n", handle);
-        goto fail;
-    }
-    if (destFile->getDevice()->sendObject(srcInfo, srcFD))
-        ret = 0;
-
-fail:
-    delete destFile;
-    delete srcInfo;
-    delete destInfo;
-    if (srcFD >= 0)
-        close(srcFD);
-    printf("returning %d\n", ret);
-    return ret;
-}
-
-typedef int (* command_func)(int argc, char* argv[]);
-
-struct command_table_entry {
-    const char* name;
-    command_func func;
-};
-
-const command_table_entry command_list[] = {
-    {   "cd",       set_cwd         },
-    {   "ls",       list            },
-    {   "get",      get_file        },
-    {   "put",      put_file        },
-    {   NULL,       NULL            },
-};
-
-
-static int do_command(int argc, char* argv[]) {
-    const command_table_entry* command = command_list;
-    const char* name = *argv++;
-    argc--;
-
-    while (command->name) {
-        if (!strcmp(command->name, name))
-            return command->func(argc, argv);
-        else
-            command++;
-    }
-    fprintf(stderr, "unknown command %s\n", name);
-    return -1;
-}
-
-static int shell() {
-    int argc;
-    int result = 0;
-#define MAX_ARGS    100
-    char* argv[MAX_ARGS];
-
-#if HAVE_READLINE
-    using_history();
-#endif
-
-    while (1) {
-#if HAVE_READLINE
-        char* line = readline(PROMPT);
-        if (!line) {
-            printf("\n");
-            exit(0);
-        }
-#else
-        char    buffer[1000];
-        printf("%s", PROMPT);
-        char* line = NULL;
-        size_t length = 0;
-
-        buffer[0] = 0;
-        fgets(buffer, sizeof(buffer), stdin);
-        int count = strlen(buffer);
-        if (count > 0 && buffer[0] == (char)EOF) {
-            printf("\n");
-            exit(0);
-        }
-        if (count > 0 && line[count - 1] == '\n')
-            line[count - 1] == 0;
-#endif
-        char* tok = strtok(line, " \t\n\r");
-        if (!tok)
-            continue;
-        if (!strcmp(tok, "quit") || !strcmp(tok, "exit")) {
-            exit(0);
-        }
-#if HAVE_READLINE
-        add_history(line);
-#endif
-        argc = 0;
-        while (tok) {
-            if (argc + 1 == MAX_ARGS) {
-                fprintf(stderr, "too many arguments\n");
-                result = -1;
-                goto bottom_of_loop;
-            }
-
-            argv[argc++] = strdup(tok);
-            tok = strtok(NULL, " \t\n\r");
-        }
-
-        result = do_command(argc, argv);
-
-bottom_of_loop:
-        for (int i = 0; i < argc; i++)
-            free(argv[i]);
-        free(line);
-    }
-
-    return result;
-}
-
-int main(int argc, char* argv[]) {
-    init();
-
-    if (argc == 1)
-        return shell();
-    else
-        return do_command(argc - 1, argv + 1);
-}
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index c18262e..5c67da7 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.database.ContentObserver;
 import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
 import android.net.MobileDataStateTracker;
@@ -29,8 +30,9 @@
 import android.net.LinkProperties;
 import android.net.NetworkStateTracker;
 import android.net.NetworkUtils;
+import android.net.Proxy;
+import android.net.ProxyProperties;
 import android.net.wifi.WifiStateTracker;
-import android.net.NetworkUtils;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -55,13 +57,12 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.net.InetAddress;
+import java.net.InetSocketAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.GregorianCalendar;
 import java.util.List;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
 
 /**
  * @hide
@@ -179,6 +180,12 @@
     private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK =
             MAX_NETWORK_STATE_TRACKER_EVENT + 8;
 
+    /**
+     * used internally to reload global proxy settings
+     */
+    private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY =
+            MAX_NETWORK_STATE_TRACKER_EVENT + 9;
+
     private Handler mHandler;
 
     // list of DeathRecipients used to make sure features are turned off when
@@ -199,6 +206,14 @@
     private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
     private ArrayList mInetLog;
 
+    // track the current default http proxy - tell the world if we get a new one (real change)
+    private ProxyProperties mDefaultProxy = null;
+    // track the global proxy.
+    private ProxyProperties mGlobalProxy = null;
+    private final Object mGlobalProxyLock = new Object();
+
+    private SettingsObserver mSettingsObserver;
+
     private static class NetworkAttributes {
         /**
          * Class for holding settings read from resources.
@@ -412,6 +427,9 @@
         if (DBG) {
             mInetLog = new ArrayList();
         }
+
+        mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);
+        mSettingsObserver.observe(mContext);
     }
 
 
@@ -1303,6 +1321,8 @@
                 mInitialBroadcast = null;
             }
         }
+        // load the global proxy at startup
+        mHandler.sendMessage(mHandler.obtainMessage(EVENT_APPLY_GLOBAL_HTTP_PROXY));
     }
 
     private void handleConnect(NetworkInfo info) {
@@ -1380,6 +1400,7 @@
 
         if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
             if (mNetAttributes[netType].isDefault()) {
+                handleApplyDefaultProxy(netType);
                 addDefaultRoute(mNetTrackers[netType]);
             } else {
                 addPrivateDnsRoutes(mNetTrackers[netType]);
@@ -1783,10 +1804,9 @@
                     }
                     break;
                 case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
-                    // TODO - make this handle ip/proxy/gateway/dns changes
                     info = (NetworkInfo) msg.obj;
                     type = info.getType();
-                    handleDnsConfigurationChange(type);
+                    handleConnectivityChange(type);
                     break;
                 case EVENT_CLEAR_NET_TRANSITION_WAKELOCK:
                     String causedBy = null;
@@ -1838,6 +1858,10 @@
                     handleSetMobileData(enabled);
                     break;
                 }
+                case EVENT_APPLY_GLOBAL_HTTP_PROXY:
+                {
+                    handleDeprecatedGlobalHttpProxy();
+                }
             }
         }
     }
@@ -2037,4 +2061,113 @@
         sendInetConditionBroadcast(networkInfo);
         return;
     }
+
+    public synchronized ProxyProperties getProxy() {
+        if (mGlobalProxy != null) return mGlobalProxy;
+        if (mDefaultProxy != null) return mDefaultProxy;
+        return null;
+    }
+
+    public void setGlobalProxy(ProxyProperties proxyProperties) {
+        enforceChangePermission();
+        synchronized (mGlobalProxyLock) {
+            if (proxyProperties == mGlobalProxy) return;
+            if (proxyProperties != null && proxyProperties.equals(mGlobalProxy)) return;
+            if (mGlobalProxy != null && mGlobalProxy.equals(proxyProperties)) return;
+
+            String host = "";
+            int port = 0;
+            String exclList = "";
+            if (proxyProperties != null && !TextUtils.isEmpty(proxyProperties.getHost())) {
+                mGlobalProxy = new ProxyProperties(proxyProperties);
+                host = mGlobalProxy.getHost();
+                port = mGlobalProxy.getPort();
+                exclList = mGlobalProxy.getExclusionList();
+            } else {
+                mGlobalProxy = null;
+            }
+            ContentResolver res = mContext.getContentResolver();
+            Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST, host);
+            Settings.Secure.putInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, port);
+            Settings.Secure.putString(res,Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
+                    exclList);
+        }
+
+        if (mGlobalProxy == null) {
+            proxyProperties = mDefaultProxy;
+        }
+        sendProxyBroadcast(proxyProperties);
+    }
+
+    public ProxyProperties getGlobalProxy() {
+        synchronized (mGlobalProxyLock) {
+            return mGlobalProxy;
+        }
+    }
+
+    private void handleApplyDefaultProxy(int type) {
+        // check if new default - push it out to all VM if so
+        ProxyProperties proxy = mNetTrackers[type].getLinkProperties().getHttpProxy();
+        synchronized (this) {
+            if (mDefaultProxy != null && mDefaultProxy.equals(proxy)) return;
+            if (mDefaultProxy == proxy) return;
+            if (!TextUtils.isEmpty(proxy.getHost())) {
+                mDefaultProxy = proxy;
+            } else {
+                mDefaultProxy = null;
+            }
+        }
+        if (DBG) Slog.d(TAG, "changing default proxy to " + proxy);
+        if ((proxy == null && mGlobalProxy == null) || proxy.equals(mGlobalProxy)) return;
+        if (mGlobalProxy != null) return;
+        sendProxyBroadcast(proxy);
+    }
+
+    private void handleDeprecatedGlobalHttpProxy() {
+        String proxy = Settings.Secure.getString(mContext.getContentResolver(),
+                Settings.Secure.HTTP_PROXY);
+        if (!TextUtils.isEmpty(proxy)) {
+            String data[] = proxy.split(":");
+            String proxyHost =  data[0];
+            int proxyPort = 8080;
+            if (data.length > 1) {
+                try {
+                    proxyPort = Integer.parseInt(data[1]);
+                } catch (NumberFormatException e) {
+                    return;
+                }
+            }
+            ProxyProperties p = new ProxyProperties(data[0], proxyPort, "");
+            setGlobalProxy(p);
+        }
+    }
+
+    private void sendProxyBroadcast(ProxyProperties proxy) {
+        Slog.d(TAG, "sending Proxy Broadcast for " + proxy);
+        Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
+        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+        intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
+        mContext.sendBroadcast(intent);
+    }
+
+    private static class SettingsObserver extends ContentObserver {
+        private int mWhat;
+        private Handler mHandler;
+        SettingsObserver(Handler handler, int what) {
+            super(handler);
+            mHandler = handler;
+            mWhat = what;
+        }
+
+        void observe(Context context) {
+            ContentResolver resolver = context.getContentResolver();
+            resolver.registerContentObserver(Settings.Secure.getUriFor(
+                    Settings.Secure.HTTP_PROXY), false, this);
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            mHandler.obtainMessage(mWhat).sendToTarget();
+        }
+    }
 }
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index 3dcad38..2b43b013 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -1757,10 +1757,19 @@
         }
         // Remove white spaces
         proxySpec = proxySpec.trim();
+        String data[] = proxySpec.split(":");
+        int proxyPort = 8080;
+        if (data.length > 1) {
+            try {
+                proxyPort = Integer.parseInt(data[1]);
+            } catch (NumberFormatException e) {}
+        }
         exclusionList = exclusionList.trim();
         ContentResolver res = mContext.getContentResolver();
-        Settings.Secure.putString(res, Settings.Secure.HTTP_PROXY, proxySpec);
-        Settings.Secure.putString(res, Settings.Secure.HTTP_PROXY_EXCLUSION_LIST, exclusionList);
+        Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST, data[0]);
+        Settings.Secure.putInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, proxyPort);
+        Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
+                exclusionList);
     }
 
     @Override
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 1ec8a22..e815524 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -76,6 +76,8 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
+import android.net.Proxy;
+import android.net.ProxyProperties;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Build;
@@ -127,6 +129,7 @@
 import java.io.PrintWriter;
 import java.lang.IllegalStateException;
 import java.lang.ref.WeakReference;
+import java.net.InetSocketAddress;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -960,6 +963,7 @@
     static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
     static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
     static final int CLEAR_DNS_CACHE = 28;
+    static final int UPDATE_HTTP_PROXY = 29;
 
     AlertDialog mUidAlert;
 
@@ -1125,6 +1129,30 @@
                     }
                 }
             } break;
+            case UPDATE_HTTP_PROXY: {
+                ProxyProperties proxy = (ProxyProperties)msg.obj;
+                String host = "";
+                String port = "";
+                String exclList = "";
+                if (proxy != null) {
+                    host = proxy.getHost();
+                    port = Integer.toString(proxy.getPort());
+                    exclList = proxy.getExclusionList();
+                }
+                synchronized (ActivityManagerService.this) {
+                    for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
+                        ProcessRecord r = mLruProcesses.get(i);
+                        if (r.thread != null) {
+                            try {
+                                r.thread.setHttpProxy(host, port, exclList);
+                            } catch (RemoteException ex) {
+                                Slog.w(TAG, "Failed to update http proxy for: " +
+                                        r.info.processName);
+                            }
+                        }
+                    }
+                }
+            } break;
             case SHOW_UID_ERROR_MSG: {
                 // XXX This is a temporary dialog, no need to localize.
                 AlertDialog d = new BaseErrorDialog(mContext);
@@ -10402,6 +10430,11 @@
             mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
         }
 
+        if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
+            ProxyProperties proxy = intent.getParcelableExtra("proxy");
+            mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
+        }
+
         /*
          * Prevent non-system code (defined here to be non-persistent
          * processes) from sending protected broadcasts.
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 70328f7..06c7c1b 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -1007,14 +1007,9 @@
             ApnSetting apn = mPendingDataConnection.getApn();
             if (apn.proxy != null && apn.proxy.length() != 0) {
                 try {
-                    ProxyProperties proxy = new ProxyProperties();
-                    proxy.setSocketAddress(new InetSocketAddress(InetAddress.getByName(apn.proxy),
-                            Integer.parseInt(apn.port)));
+                    ProxyProperties proxy = new ProxyProperties(apn.proxy,
+                            Integer.parseInt(apn.port), null);
                     mLinkProperties.setHttpProxy(proxy);
-                } catch (UnknownHostException e) {
-                    loge("UnknownHostException making ProxyProperties: " + e);
-                } catch (SecurityException e) {
-                    loge("SecurityException making ProxyProperties: " + e);
                 } catch (NumberFormatException e) {
                     loge("NumberFormatException making ProxyProperties (" + apn.port +
                             "): " + e);
diff --git a/wifi/java/android/net/wifi/SupplicantStateTracker.java b/wifi/java/android/net/wifi/SupplicantStateTracker.java
new file mode 100644
index 0000000..a83a0ad
--- /dev/null
+++ b/wifi/java/android/net/wifi/SupplicantStateTracker.java
@@ -0,0 +1,333 @@
+/*
+ * 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 android.net.wifi;
+
+import com.android.internal.util.HierarchicalState;
+import com.android.internal.util.HierarchicalStateMachine;
+
+import android.net.wifi.WifiStateMachine.StateChangeResult;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * Tracks the state changes in supplicant and provides functionality
+ * that is based on these state changes:
+ * - detect a failed WPA handshake that loops indefinitely
+ * - password failure handling
+ * - Enable networks after a WPS success/failure
+ */
+class SupplicantStateTracker extends HierarchicalStateMachine {
+
+    private static final String TAG = "SupplicantStateTracker";
+    private static final boolean DBG = false;
+
+    private WifiStateMachine mWifiStateMachine;
+    private int mPasswordFailuresCount = 0;
+    /* Indicates authentication failure in supplicant broadcast.
+     * TODO: enhance auth failure reporting to include notification
+     * for all type of failures: EAP, WPS & WPA networks */
+    private boolean mAuthFailureInSupplicantBroadcast = false;
+
+    /* Maximum retries on a password failure notification */
+    private static final int MAX_RETRIES_ON_PASSWORD_FAILURE = 2;
+
+    /* Track if WPS was started since we need to re-enable networks
+     * and load configuration afterwards */
+    private boolean mWpsStarted = false;
+
+    private Context mContext;
+
+    private HierarchicalState mUninitializedState = new UninitializedState();
+    private HierarchicalState mDefaultState = new DefaultState();
+    private HierarchicalState mInactiveState = new InactiveState();
+    private HierarchicalState mDisconnectState = new DisconnectedState();
+    private HierarchicalState mScanState = new ScanState();
+    private HierarchicalState mHandshakeState = new HandshakeState();
+    private HierarchicalState mCompletedState = new CompletedState();
+    private HierarchicalState mDormantState = new DormantState();
+
+    public SupplicantStateTracker(Context context, WifiStateMachine wsm, Handler target) {
+        super(TAG, target.getLooper());
+
+        mContext = context;
+        mWifiStateMachine = wsm;
+        addState(mDefaultState);
+            addState(mUninitializedState, mDefaultState);
+            addState(mInactiveState, mDefaultState);
+            addState(mDisconnectState, mDefaultState);
+            addState(mScanState, mDefaultState);
+            addState(mHandshakeState, mDefaultState);
+            addState(mCompletedState, mDefaultState);
+            addState(mDormantState, mDefaultState);
+
+        setInitialState(mUninitializedState);
+
+        //start the state machine
+        start();
+    }
+
+    public void resetSupplicantState() {
+        transitionTo(mUninitializedState);
+    }
+
+
+    private void transitionOnSupplicantStateChange(StateChangeResult stateChangeResult) {
+        SupplicantState supState = (SupplicantState) stateChangeResult.state;
+
+        if (DBG) Log.d(TAG, "Supplicant state: " + supState.toString() + "\n");
+
+        switch (supState) {
+            case DISCONNECTED:
+                transitionTo(mDisconnectState);
+                break;
+            case SCANNING:
+                transitionTo(mScanState);
+                break;
+            case ASSOCIATING:
+            case ASSOCIATED:
+            case FOUR_WAY_HANDSHAKE:
+            case GROUP_HANDSHAKE:
+                transitionTo(mHandshakeState);
+                break;
+            case COMPLETED:
+                transitionTo(mCompletedState);
+                break;
+            case DORMANT:
+                transitionTo(mDormantState);
+                break;
+            case INACTIVE:
+                transitionTo(mInactiveState);
+                break;
+            case UNINITIALIZED:
+            case INVALID:
+                transitionTo(mUninitializedState);
+                break;
+            default:
+                Log.e(TAG, "Unknown supplicant state " + supState);
+                break;
+        }
+    }
+
+    private void sendSupplicantStateChangedBroadcast(StateChangeResult sc, boolean failedAuth) {
+        Intent intent = new Intent(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
+                | Intent.FLAG_RECEIVER_REPLACE_PENDING);
+        intent.putExtra(WifiManager.EXTRA_NEW_STATE, (Parcelable)sc.state);
+        if (failedAuth) {
+            intent.putExtra(
+                WifiManager.EXTRA_SUPPLICANT_ERROR,
+                WifiManager.ERROR_AUTHENTICATING);
+        }
+        mContext.sendStickyBroadcast(intent);
+    }
+
+    /********************************************************
+     * HSM states
+     *******************************************************/
+
+    class DefaultState extends HierarchicalState {
+        @Override
+         public void enter() {
+             if (DBG) Log.d(TAG, getName() + "\n");
+         }
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+            switch (message.what) {
+                case WifiStateMachine.PASSWORD_MAY_BE_INCORRECT_EVENT:
+                    mPasswordFailuresCount++;
+                    mAuthFailureInSupplicantBroadcast = true;
+                    break;
+                case WifiStateMachine.CMD_START_WPS_PBC:
+                case WifiStateMachine.CMD_START_WPS_PIN_FROM_AP:
+                case WifiStateMachine.CMD_START_WPS_PIN_FROM_DEVICE:
+                    mWpsStarted = true;
+                    break;
+                case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT:
+                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
+                    sendSupplicantStateChangedBroadcast(stateChangeResult,
+                            mAuthFailureInSupplicantBroadcast);
+                    mAuthFailureInSupplicantBroadcast = false;
+                    transitionOnSupplicantStateChange(stateChangeResult);
+                    break;
+                default:
+                    Log.e(TAG, "Ignoring " + message);
+                    break;
+            }
+            return HANDLED;
+        }
+    }
+
+    class UninitializedState extends HierarchicalState {
+        @Override
+         public void enter() {
+             if (DBG) Log.d(TAG, getName() + "\n");
+             mWifiStateMachine.setNetworkAvailable(false);
+         }
+        @Override
+        public void exit() {
+            mWifiStateMachine.setNetworkAvailable(true);
+        }
+    }
+
+    class InactiveState extends HierarchicalState {
+        @Override
+         public void enter() {
+             if (DBG) Log.d(TAG, getName() + "\n");
+             /* A failed WPS connection */
+             if (mWpsStarted) {
+                 Log.e(TAG, "WPS set up failed, enabling other networks");
+                 WifiConfigStore.enableAllNetworks();
+                 mWpsStarted = false;
+             }
+             mWifiStateMachine.setNetworkAvailable(false);
+         }
+        @Override
+        public void exit() {
+            mWifiStateMachine.setNetworkAvailable(true);
+        }
+    }
+
+
+    class DisconnectedState extends HierarchicalState {
+        @Override
+         public void enter() {
+             if (DBG) Log.d(TAG, getName() + "\n");
+             /* If a disconnect event happens after password key failure
+              * exceeds maximum retries, disable the network
+              */
+
+             Message message = getCurrentMessage();
+             StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
+
+             if (mPasswordFailuresCount >= MAX_RETRIES_ON_PASSWORD_FAILURE) {
+                 Log.d(TAG, "Failed to authenticate, disabling network " +
+                         stateChangeResult.networkId);
+                 WifiConfigStore.disableNetwork(stateChangeResult.networkId);
+                 mPasswordFailuresCount = 0;
+             }
+         }
+    }
+
+    class ScanState extends HierarchicalState {
+        @Override
+         public void enter() {
+             if (DBG) Log.d(TAG, getName() + "\n");
+         }
+    }
+
+    class HandshakeState extends HierarchicalState {
+        /**
+         * The max number of the WPA supplicant loop iterations before we
+         * decide that the loop should be terminated:
+         */
+        private static final int MAX_SUPPLICANT_LOOP_ITERATIONS = 4;
+        private int mLoopDetectIndex;
+        private int mLoopDetectCount;
+
+        @Override
+         public void enter() {
+             if (DBG) Log.d(TAG, getName() + "\n");
+             mLoopDetectIndex = 0;
+             mLoopDetectCount = 0;
+         }
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+            switch (message.what) {
+                case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT:
+                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
+                    SupplicantState state = (SupplicantState) stateChangeResult.state;
+                    if (state == SupplicantState.ASSOCIATING ||
+                            state == SupplicantState.ASSOCIATED ||
+                            state == SupplicantState.FOUR_WAY_HANDSHAKE ||
+                            state == SupplicantState.GROUP_HANDSHAKE) {
+                        if (mLoopDetectIndex > state.ordinal()) {
+                            mLoopDetectCount++;
+                        }
+                        if (mLoopDetectCount > MAX_SUPPLICANT_LOOP_ITERATIONS) {
+                            Log.d(TAG, "Supplicant loop detected, disabling network " +
+                                    stateChangeResult.networkId);
+                            WifiConfigStore.disableNetwork(stateChangeResult.networkId);
+                        }
+                        mLoopDetectIndex = state.ordinal();
+                        sendSupplicantStateChangedBroadcast(stateChangeResult,
+                                mAuthFailureInSupplicantBroadcast);
+                    } else {
+                        //Have the DefaultState handle the transition
+                        return NOT_HANDLED;
+                    }
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
+        }
+    }
+
+    class CompletedState extends HierarchicalState {
+        @Override
+         public void enter() {
+             if (DBG) Log.d(TAG, getName() + "\n");
+             /* Reset password failure count */
+             mPasswordFailuresCount = 0;
+
+             /* A successful WPS connection */
+             if (mWpsStarted) {
+                 WifiConfigStore.enableAllNetworks();
+                 WifiConfigStore.loadConfiguredNetworks();
+                 mWpsStarted = false;
+             }
+         }
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+            switch(message.what) {
+                case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT:
+                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
+                    SupplicantState state = (SupplicantState) stateChangeResult.state;
+                    sendSupplicantStateChangedBroadcast(stateChangeResult,
+                            mAuthFailureInSupplicantBroadcast);
+                    /* Ignore a re-auth in completed state */
+                    if (state == SupplicantState.ASSOCIATING ||
+                            state == SupplicantState.ASSOCIATED ||
+                            state == SupplicantState.FOUR_WAY_HANDSHAKE ||
+                            state == SupplicantState.GROUP_HANDSHAKE ||
+                            state == SupplicantState.COMPLETED) {
+                        break;
+                    }
+                    transitionOnSupplicantStateChange(stateChangeResult);
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
+        }
+    }
+
+    //TODO: remove after getting rid of the state in supplicant
+    class DormantState extends HierarchicalState {
+        @Override
+        public void enter() {
+            if (DBG) Log.d(TAG, getName() + "\n");
+        }
+    }
+}
\ No newline at end of file
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index 04b3891..24f6f31 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -595,9 +595,9 @@
                                 out.writeUTF(PROXY_SETTINGS_KEY);
                                 out.writeUTF(config.proxySettings.toString());
                                 out.writeUTF(PROXY_HOST_KEY);
-                                out.writeUTF(proxyProperties.getSocketAddress().getHostName());
+                                out.writeUTF(proxyProperties.getHost());
                                 out.writeUTF(PROXY_PORT_KEY);
-                                out.writeInt(proxyProperties.getSocketAddress().getPort());
+                                out.writeInt(proxyProperties.getPort());
                                 out.writeUTF(EXCLUSION_LIST_KEY);
                                 out.writeUTF(exclusionList);
                                 writeToFile = true;
@@ -716,10 +716,8 @@
                             switch (proxySettings) {
                                 case STATIC:
                                     config.proxySettings = proxySettings;
-                                    ProxyProperties proxyProperties = new ProxyProperties();
-                                    proxyProperties.setSocketAddress(
-                                            new InetSocketAddress(proxyHost, proxyPort));
-                                    proxyProperties.setExclusionList(exclusionList);
+                                    ProxyProperties proxyProperties =
+                                        new ProxyProperties(proxyHost, proxyPort, exclusionList);
                                     linkProperties.setHttpProxy(proxyProperties);
                                     break;
                                 case NONE:
@@ -1012,42 +1010,13 @@
 
         switch (newConfig.proxySettings) {
             case STATIC:
-                InetSocketAddress newSockAddr = null;
-                String newExclusionList = null;
-                InetSocketAddress currentSockAddr = null;
-                String currentExclusionList = null;
-
                 ProxyProperties newHttpProxy = newConfig.linkProperties.getHttpProxy();
-                if (newHttpProxy != null) {
-                    newSockAddr = newHttpProxy.getSocketAddress();
-                    newExclusionList = newHttpProxy.getExclusionList();
-                }
-
                 ProxyProperties currentHttpProxy = currentConfig.linkProperties.getHttpProxy();
-                if (currentHttpProxy != null) {
-                    currentSockAddr =  currentHttpProxy.getSocketAddress();
-                    currentExclusionList = currentHttpProxy.getExclusionList();
-                }
 
-                boolean socketAddressDiffers = false;
-                boolean exclusionListDiffers = false;
-
-                if (newSockAddr != null && currentSockAddr != null ) {
-                    socketAddressDiffers = !currentSockAddr.equals(newSockAddr);
-                } else if (newSockAddr != null || currentSockAddr != null) {
-                    socketAddressDiffers = true;
-                }
-
-                if (newExclusionList != null && currentExclusionList != null) {
-                    exclusionListDiffers = !currentExclusionList.equals(newExclusionList);
-                } else if (newExclusionList != null || currentExclusionList != null) {
-                    exclusionListDiffers = true;
-                }
-
-                if ((currentConfig.proxySettings != newConfig.proxySettings) ||
-                        socketAddressDiffers ||
-                        exclusionListDiffers) {
-                    proxyChanged = true;
+                if (newHttpProxy != null) {
+                    proxyChanged = !newHttpProxy.equals(currentHttpProxy);
+                } else {
+                    proxyChanged = (currentHttpProxy != null);
                 }
                 break;
             case NONE:
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 95e2df3..90abd02 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -49,8 +49,6 @@
 import android.net.LinkProperties;
 import android.os.Binder;
 import android.os.Message;
-import android.os.Parcelable;
-import android.os.Handler;
 import android.os.IBinder;
 import android.os.INetworkManagementService;
 import android.os.PowerManager;
@@ -93,8 +91,6 @@
  *
  * @hide
  */
-//TODO: we still need frequent scanning for the case when
-// we issue disconnect but need scan results for open network notification
 public class WifiStateMachine extends HierarchicalStateMachine {
 
     private static final String TAG = "WifiStateMachine";
@@ -120,11 +116,17 @@
     private String mLastBssid;
     private int mLastNetworkId;
     private boolean mEnableRssiPolling = false;
-    private boolean mPasswordKeyMayBeIncorrect = false;
+    private int mRssiPollToken = 0;
     private int mReconnectCount = 0;
     private boolean mIsScanMode = false;
 
     /**
+     * Interval in milliseconds between polling for RSSI
+     * and linkspeed information
+     */
+    private static final int POLL_RSSI_INTERVAL_MSECS = 3000;
+
+    /**
      * Instance of the bluetooth headset helper. This needs to be created
      * early because there is a delay before it actually 'connects', as
      * noted by its javadoc. If we check before it is connected, it will be
@@ -148,9 +150,6 @@
     /* Connection to a specific network involves disabling all networks,
      * this flag tracks if networks need to be re-enabled */
     private boolean mEnableAllNetworks = false;
-    /* Track if WPS was started since we need to re-enable networks
-     * and load configuration afterwards */
-    private boolean mWpsStarted = false;
 
     private AlarmManager mAlarmManager;
     private PendingIntent mScanIntent;
@@ -166,95 +165,95 @@
     private static final int EVENTLOG_SUPPLICANT_STATE_CHANGED  = 50023;
 
     /* Load the driver */
-    private static final int CMD_LOAD_DRIVER                      = 1;
+    static final int CMD_LOAD_DRIVER                      = 1;
     /* Unload the driver */
-    private static final int CMD_UNLOAD_DRIVER                    = 2;
+    static final int CMD_UNLOAD_DRIVER                    = 2;
     /* Indicates driver load succeeded */
-    private static final int CMD_LOAD_DRIVER_SUCCESS              = 3;
+    static final int CMD_LOAD_DRIVER_SUCCESS              = 3;
     /* Indicates driver load failed */
-    private static final int CMD_LOAD_DRIVER_FAILURE              = 4;
+    static final int CMD_LOAD_DRIVER_FAILURE              = 4;
     /* Indicates driver unload succeeded */
-    private static final int CMD_UNLOAD_DRIVER_SUCCESS            = 5;
+    static final int CMD_UNLOAD_DRIVER_SUCCESS            = 5;
     /* Indicates driver unload failed */
-    private static final int CMD_UNLOAD_DRIVER_FAILURE            = 6;
+    static final int CMD_UNLOAD_DRIVER_FAILURE            = 6;
     /* Set bluetooth headset proxy */
-    private static final int CMD_SET_BLUETOOTH_HEADSET_PROXY      = 7;
+    static final int CMD_SET_BLUETOOTH_HEADSET_PROXY      = 7;
     /* Set bluetooth A2dp proxy */
-    private static final int CMD_SET_BLUETOOTH_A2DP_PROXY         = 8;
+    static final int CMD_SET_BLUETOOTH_A2DP_PROXY         = 8;
 
     /* Start the supplicant */
-    private static final int CMD_START_SUPPLICANT                 = 11;
+    static final int CMD_START_SUPPLICANT                 = 11;
     /* Stop the supplicant */
-    private static final int CMD_STOP_SUPPLICANT                  = 12;
+    static final int CMD_STOP_SUPPLICANT                  = 12;
     /* Start the driver */
-    private static final int CMD_START_DRIVER                     = 13;
+    static final int CMD_START_DRIVER                     = 13;
     /* Start the driver */
-    private static final int CMD_STOP_DRIVER                      = 14;
+    static final int CMD_STOP_DRIVER                      = 14;
     /* Indicates DHCP succeded */
-    private static final int CMD_IP_CONFIG_SUCCESS                = 15;
+    static final int CMD_IP_CONFIG_SUCCESS                = 15;
     /* Indicates DHCP failed */
-    private static final int CMD_IP_CONFIG_FAILURE                = 16;
+    static final int CMD_IP_CONFIG_FAILURE                = 16;
     /* Re-configure interface */
-    private static final int CMD_RECONFIGURE_IP                   = 17;
+    static final int CMD_RECONFIGURE_IP                   = 17;
 
 
     /* Start the soft access point */
-    private static final int CMD_START_AP                         = 21;
+    static final int CMD_START_AP                         = 21;
     /* Stop the soft access point */
-    private static final int CMD_STOP_AP                          = 22;
+    static final int CMD_STOP_AP                          = 22;
 
 
     /* Supplicant events */
     /* Connection to supplicant established */
-    private static final int SUP_CONNECTION_EVENT                 = 31;
+    static final int SUP_CONNECTION_EVENT                 = 31;
     /* Connection to supplicant lost */
-    private static final int SUP_DISCONNECTION_EVENT              = 32;
+    static final int SUP_DISCONNECTION_EVENT              = 32;
     /* Driver start completed */
-    private static final int DRIVER_START_EVENT                   = 33;
+    static final int DRIVER_START_EVENT                   = 33;
     /* Driver stop completed */
-    private static final int DRIVER_STOP_EVENT                    = 34;
+    static final int DRIVER_STOP_EVENT                    = 34;
     /* Network connection completed */
-    private static final int NETWORK_CONNECTION_EVENT             = 36;
+    static final int NETWORK_CONNECTION_EVENT             = 36;
     /* Network disconnection completed */
-    private static final int NETWORK_DISCONNECTION_EVENT          = 37;
+    static final int NETWORK_DISCONNECTION_EVENT          = 37;
     /* Scan results are available */
-    private static final int SCAN_RESULTS_EVENT                   = 38;
+    static final int SCAN_RESULTS_EVENT                   = 38;
     /* Supplicate state changed */
-    private static final int SUPPLICANT_STATE_CHANGE_EVENT        = 39;
+    static final int SUPPLICANT_STATE_CHANGE_EVENT        = 39;
     /* Password may be incorrect */
-    private static final int PASSWORD_MAY_BE_INCORRECT_EVENT      = 40;
+    static final int PASSWORD_MAY_BE_INCORRECT_EVENT      = 40;
 
     /* Supplicant commands */
     /* Is supplicant alive ? */
-    private static final int CMD_PING_SUPPLICANT                  = 51;
+    static final int CMD_PING_SUPPLICANT                  = 51;
     /* Add/update a network configuration */
-    private static final int CMD_ADD_OR_UPDATE_NETWORK            = 52;
+    static final int CMD_ADD_OR_UPDATE_NETWORK            = 52;
     /* Delete a network */
-    private static final int CMD_REMOVE_NETWORK                   = 53;
+    static final int CMD_REMOVE_NETWORK                   = 53;
     /* Enable a network. The device will attempt a connection to the given network. */
-    private static final int CMD_ENABLE_NETWORK                   = 54;
+    static final int CMD_ENABLE_NETWORK                   = 54;
     /* Disable a network. The device does not attempt a connection to the given network. */
-    private static final int CMD_DISABLE_NETWORK                  = 55;
+    static final int CMD_DISABLE_NETWORK                  = 55;
     /* Blacklist network. De-prioritizes the given BSSID for connection. */
-    private static final int CMD_BLACKLIST_NETWORK                = 56;
+    static final int CMD_BLACKLIST_NETWORK                = 56;
     /* Clear the blacklist network list */
-    private static final int CMD_CLEAR_BLACKLIST                  = 57;
+    static final int CMD_CLEAR_BLACKLIST                  = 57;
     /* Save configuration */
-    private static final int CMD_SAVE_CONFIG                      = 58;
+    static final int CMD_SAVE_CONFIG                      = 58;
 
     /* Supplicant commands after driver start*/
     /* Initiate a scan */
-    private static final int CMD_START_SCAN                       = 71;
+    static final int CMD_START_SCAN                       = 71;
     /* Set scan mode. CONNECT_MODE or SCAN_ONLY_MODE */
-    private static final int CMD_SET_SCAN_MODE                    = 72;
+    static final int CMD_SET_SCAN_MODE                    = 72;
     /* Set scan type. SCAN_ACTIVE or SCAN_PASSIVE */
-    private static final int CMD_SET_SCAN_TYPE                    = 73;
+    static final int CMD_SET_SCAN_TYPE                    = 73;
     /* Disconnect from a network */
-    private static final int CMD_DISCONNECT                       = 74;
+    static final int CMD_DISCONNECT                       = 74;
     /* Reconnect to a network */
-    private static final int CMD_RECONNECT                        = 75;
+    static final int CMD_RECONNECT                        = 75;
     /* Reassociate to a network */
-    private static final int CMD_REASSOCIATE                      = 76;
+    static final int CMD_REASSOCIATE                      = 76;
     /* Controls power mode and suspend mode optimizations
      *
      * When high perf mode is enabled, power mode is set to
@@ -268,30 +267,30 @@
      * - turn off roaming
      * - DTIM wake up settings
      */
-    private static final int CMD_SET_HIGH_PERF_MODE               = 77;
+    static final int CMD_SET_HIGH_PERF_MODE               = 77;
     /* Set bluetooth co-existence
      * BLUETOOTH_COEXISTENCE_MODE_ENABLED
      * BLUETOOTH_COEXISTENCE_MODE_DISABLED
      * BLUETOOTH_COEXISTENCE_MODE_SENSE
      */
-    private static final int CMD_SET_BLUETOOTH_COEXISTENCE        = 78;
+    static final int CMD_SET_BLUETOOTH_COEXISTENCE        = 78;
     /* Enable/disable bluetooth scan mode
      * true(1)
      * false(0)
      */
-    private static final int CMD_SET_BLUETOOTH_SCAN_MODE          = 79;
+    static final int CMD_SET_BLUETOOTH_SCAN_MODE          = 79;
     /* Set the country code */
-    private static final int CMD_SET_COUNTRY_CODE                 = 80;
+    static final int CMD_SET_COUNTRY_CODE                 = 80;
     /* Request connectivity manager wake lock before driver stop */
-    private static final int CMD_REQUEST_CM_WAKELOCK              = 81;
+    static final int CMD_REQUEST_CM_WAKELOCK              = 81;
     /* Enables RSSI poll */
-    private static final int CMD_ENABLE_RSSI_POLL                 = 82;
+    static final int CMD_ENABLE_RSSI_POLL                 = 82;
     /* RSSI poll */
-    private static final int CMD_RSSI_POLL                        = 83;
+    static final int CMD_RSSI_POLL                        = 83;
     /* Set up packet filtering */
-    private static final int CMD_START_PACKET_FILTERING           = 84;
+    static final int CMD_START_PACKET_FILTERING           = 84;
     /* Clear packet filter */
-    private static final int CMD_STOP_PACKET_FILTERING            = 85;
+    static final int CMD_STOP_PACKET_FILTERING            = 85;
     /* Connect to a specified network (network id
      * or WifiConfiguration) This involves increasing
      * the priority of the network, enabling the network
@@ -300,32 +299,29 @@
      * an existing network. All the networks get enabled
      * upon a successful connection or a failure.
      */
-    private static final int CMD_CONNECT_NETWORK                  = 86;
+    static final int CMD_CONNECT_NETWORK                  = 86;
     /* Save the specified network. This involves adding
      * an enabled network (if new) and updating the
      * config and issuing a save on supplicant config.
      */
-    private static final int CMD_SAVE_NETWORK                     = 87;
+    static final int CMD_SAVE_NETWORK                     = 87;
     /* Delete the specified network. This involves
      * removing the network and issuing a save on
      * supplicant config.
      */
-    private static final int CMD_FORGET_NETWORK                   = 88;
+    static final int CMD_FORGET_NETWORK                   = 88;
     /* Start Wi-Fi protected setup push button configuration */
-    private static final int CMD_START_WPS_PBC                    = 89;
+    static final int CMD_START_WPS_PBC                    = 89;
     /* Start Wi-Fi protected setup pin method configuration with pin obtained from AP */
-    private static final int CMD_START_WPS_PIN_FROM_AP            = 90;
+    static final int CMD_START_WPS_PIN_FROM_AP            = 90;
     /* Start Wi-Fi protected setup pin method configuration with pin obtained from device */
-    private static final int CMD_START_WPS_PIN_FROM_DEVICE        = 91;
+    static final int CMD_START_WPS_PIN_FROM_DEVICE        = 91;
     /* Set the frequency band */
-    private static final int CMD_SET_FREQUENCY_BAND               = 92;
+    static final int CMD_SET_FREQUENCY_BAND               = 92;
 
-    /**
-     * Interval in milliseconds between polling for connection
-     * status items that are not sent via asynchronous events.
-     * An example is RSSI (signal strength).
-     */
-    private static final int POLL_RSSI_INTERVAL_MSECS = 3000;
+    /* Commands from the SupplicantStateTracker */
+    /* Indicates whether a wifi network is available for connection */
+    static final int CMD_SET_NETWORK_AVAILABLE             = 111;
 
     private static final int CONNECT_MODE   = 1;
     private static final int SCAN_ONLY_MODE = 2;
@@ -463,7 +459,7 @@
         mDhcpInfo = new DhcpInfo();
         mWifiInfo = new WifiInfo();
         mInterfaceName = SystemProperties.get("wifi.interface", "tiwlan0");
-        mSupplicantStateTracker = new SupplicantStateTracker(context, getHandler());
+        mSupplicantStateTracker = new SupplicantStateTracker(context, this, getHandler());
 
         mLinkProperties = new LinkProperties();
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
@@ -985,8 +981,6 @@
         sb.append("mLastBssid ").append(mLastBssid).append(LS);
         sb.append("mLastNetworkId ").append(mLastNetworkId).append(LS);
         sb.append("mEnableAllNetworks ").append(mEnableAllNetworks).append(LS);
-        sb.append("mEnableRssiPolling ").append(mEnableRssiPolling).append(LS);
-        sb.append("mPasswordKeyMayBeIncorrect ").append(mPasswordKeyMayBeIncorrect).append(LS);
         sb.append("mReconnectCount ").append(mReconnectCount).append(LS);
         sb.append("mIsScanMode ").append(mIsScanMode).append(LS);
         sb.append("Supplicant status").append(LS)
@@ -1215,6 +1209,44 @@
         return null;
     }
 
+    /*
+     * Fetch RSSI and linkspeed on current connection
+     */
+    private void fetchRssiAndLinkSpeedNative() {
+        int newRssi = WifiNative.getRssiCommand();
+        if (newRssi != -1 && -200 < newRssi && newRssi < 256) { // screen out invalid values
+            /* some implementations avoid negative values by adding 256
+             * so we need to adjust for that here.
+             */
+            if (newRssi > 0) newRssi -= 256;
+            mWifiInfo.setRssi(newRssi);
+            /*
+             * Rather then sending the raw RSSI out every time it
+             * changes, we precalculate the signal level that would
+             * be displayed in the status bar, and only send the
+             * broadcast if that much more coarse-grained number
+             * changes. This cuts down greatly on the number of
+             * broadcasts, at the cost of not mWifiInforming others
+             * interested in RSSI of all the changes in signal
+             * level.
+             */
+            // TODO: The second arg to the call below needs to be a symbol somewhere, but
+            // it's actually the size of an array of icons that's private
+            // to StatusBar Policy.
+            int newSignalLevel = WifiManager.calculateSignalLevel(newRssi, 4);
+            if (newSignalLevel != mLastSignalLevel) {
+                sendRssiChangeBroadcast(newRssi);
+            }
+            mLastSignalLevel = newSignalLevel;
+        } else {
+            mWifiInfo.setRssi(-200);
+        }
+        int newLinkSpeed = WifiNative.getLinkSpeedCommand();
+        if (newLinkSpeed != -1) {
+            mWifiInfo.setLinkSpeed(newLinkSpeed);
+        }
+    }
+
     private void setHighPerfModeEnabledNative(boolean enable) {
         if(!WifiNative.setSuspendOptimizationsCommand(!enable)) {
             Log.e(TAG, "set suspend optimizations failed!");
@@ -1336,19 +1368,6 @@
         mContext.sendBroadcast(intent);
     }
 
-    private void sendSupplicantStateChangedBroadcast(StateChangeResult sc, boolean failedAuth) {
-        Intent intent = new Intent(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
-        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
-                | Intent.FLAG_RECEIVER_REPLACE_PENDING);
-        intent.putExtra(WifiManager.EXTRA_NEW_STATE, (Parcelable)sc.state);
-        if (failedAuth) {
-            intent.putExtra(
-                WifiManager.EXTRA_SUPPLICANT_ERROR,
-                WifiManager.ERROR_AUTHENTICATING);
-        }
-        mContext.sendStickyBroadcast(intent);
-    }
-
     private void sendSupplicantConnectionChangedBroadcast(boolean connected) {
         if (!ActivityManagerNative.isSystemReady()) return;
 
@@ -1370,45 +1389,6 @@
     }
 
     /**
-     * Poll for info not reported via events
-     * RSSI & Linkspeed
-     */
-    private void requestPolledInfo() {
-        int newRssi = WifiNative.getRssiCommand();
-        if (newRssi != -1 && -200 < newRssi && newRssi < 256) { // screen out invalid values
-            /* some implementations avoid negative values by adding 256
-             * so we need to adjust for that here.
-             */
-            if (newRssi > 0) newRssi -= 256;
-            mWifiInfo.setRssi(newRssi);
-            /*
-             * Rather then sending the raw RSSI out every time it
-             * changes, we precalculate the signal level that would
-             * be displayed in the status bar, and only send the
-             * broadcast if that much more coarse-grained number
-             * changes. This cuts down greatly on the number of
-             * broadcasts, at the cost of not mWifiInforming others
-             * interested in RSSI of all the changes in signal
-             * level.
-             */
-            // TODO: The second arg to the call below needs to be a symbol somewhere, but
-            // it's actually the size of an array of icons that's private
-            // to StatusBar Policy.
-            int newSignalLevel = WifiManager.calculateSignalLevel(newRssi, 4);
-            if (newSignalLevel != mLastSignalLevel) {
-                sendRssiChangeBroadcast(newRssi);
-            }
-            mLastSignalLevel = newSignalLevel;
-        } else {
-            mWifiInfo.setRssi(-200);
-        }
-        int newLinkSpeed = WifiNative.getLinkSpeedCommand();
-        if (newLinkSpeed != -1) {
-            mWifiInfo.setLinkSpeed(newLinkSpeed);
-        }
-    }
-
-    /**
      * Resets the Wi-Fi Connections by clearing any state, resetting any sockets
      * using the interface, stopping DHCP & disabling interface
      */
@@ -1456,7 +1436,7 @@
      * WifiMonitor
      * thread.
      */
-    private static class StateChangeResult {
+    static class StateChangeResult {
         StateChangeResult(int networkId, String BSSID, Object state) {
             this.state = state;
             this.BSSID = BSSID;
@@ -1548,6 +1528,9 @@
         setWifiEnabled(true);
     }
 
+    void setNetworkAvailable(boolean available) {
+        sendMessage(CMD_SET_NETWORK_AVAILABLE, available ? 1 : 0);
+    }
 
     /********************************************************
      * HSM states
@@ -1576,7 +1559,9 @@
                     break;
                 case CMD_ENABLE_RSSI_POLL:
                     mEnableRssiPolling = (message.arg1 == 1);
-                    mSupplicantStateTracker.sendMessage(CMD_ENABLE_RSSI_POLL);
+                    break;
+                case CMD_SET_NETWORK_AVAILABLE:
+                    mNetworkInfo.setIsAvailable(message.arg1 == 1);
                     break;
                     /* Discard */
                 case CMD_LOAD_DRIVER:
@@ -1616,6 +1601,7 @@
                 case CMD_FORGET_NETWORK:
                 case CMD_START_WPS_PBC:
                 case CMD_START_WPS_PIN_FROM_AP:
+                case CMD_RSSI_POLL:
                     break;
                 default:
                     Log.e(TAG, "Error! unhandled message" + message);
@@ -2136,6 +2122,9 @@
                         WifiNative.setScanModeCommand(false);
                     }
                     break;
+                case CMD_START_SCAN:
+                    WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE);
+                    break;
                 case CMD_SET_HIGH_PERF_MODE:
                     setHighPerfModeEnabledNative(message.arg1 == 1);
                     break;
@@ -2278,9 +2267,6 @@
                         transitionTo(mDisconnectedState);
                     }
                     break;
-                case CMD_START_SCAN:
-                    WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE);
-                    break;
                     /* Ignore */
                 case CMD_DISCONNECT:
                 case CMD_RECONNECT:
@@ -2309,14 +2295,23 @@
             StateChangeResult stateChangeResult;
             switch(message.what) {
                 case PASSWORD_MAY_BE_INCORRECT_EVENT:
-                    mPasswordKeyMayBeIncorrect = true;
+                    mSupplicantStateTracker.sendMessage(PASSWORD_MAY_BE_INCORRECT_EVENT);
                     break;
                 case SUPPLICANT_STATE_CHANGE_EVENT:
                     stateChangeResult = (StateChangeResult) message.obj;
-                    mSupplicantStateTracker.handleEvent(stateChangeResult);
-                    break;
-                case CMD_START_SCAN:
-                    /* We need to set scan type in completed state */
+                    SupplicantState state = (SupplicantState) stateChangeResult.state;
+                    // Supplicant state change
+                    // [31-13] Reserved for future use
+                    // [8 - 0] Supplicant state (as defined in SupplicantState.java)
+                    // 50023 supplicant_state_changed (custom|1|5)
+                    EventLog.writeEvent(EVENTLOG_SUPPLICANT_STATE_CHANGED, state.ordinal());
+                    mWifiInfo.setSupplicantState(state);
+                    mWifiInfo.setNetworkId(stateChangeResult.networkId);
+                    if (state == SupplicantState.ASSOCIATING) {
+                        /* BSSID is valid only in ASSOCIATING state */
+                        mWifiInfo.setBSSID(stateChangeResult.BSSID);
+                    }
+
                     Message newMsg = obtainMessage();
                     newMsg.copyFrom(message);
                     mSupplicantStateTracker.sendMessage(newMsg);
@@ -2375,7 +2370,7 @@
                      * Upon success, the configuration list needs to be reloaded
                      */
                     if (success) {
-                        mWpsStarted = true;
+                        mSupplicantStateTracker.sendMessage(message.what);
                         /* Expect a disconnection from the old connection */
                         transitionTo(mDisconnectingState);
                     }
@@ -2388,7 +2383,7 @@
                     success = WifiConfigStore.startWpsWithPinFromAccessPoint(bssid, apPin);
 
                     if (success) {
-                        mWpsStarted = true;
+                        mSupplicantStateTracker.sendMessage(message.what);
                         /* Expect a disconnection from the old connection */
                         transitionTo(mDisconnectingState);
                     }
@@ -2400,7 +2395,7 @@
                     mReplyChannel.replyToMessage(message, CMD_START_WPS_PIN_FROM_DEVICE, pin);
 
                     if (success) {
-                        mWpsStarted = true;
+                        mSupplicantStateTracker.sendMessage(message.what);
                         /* Expect a disconnection from the old connection */
                         transitionTo(mDisconnectingState);
                     }
@@ -2583,6 +2578,10 @@
                       deferMessage(message);
                   }
                   break;
+                  /* Defer scan when IP is being fetched */
+              case CMD_START_SCAN:
+                  deferMessage(message);
+                  break;
               case CMD_RECONFIGURE_IP:
                   deferMessage(message);
                   break;
@@ -2619,13 +2618,11 @@
         @Override
         public void enter() {
             if (DBG) Log.d(TAG, getName() + "\n");
-            /* A successful WPS connection */
-            if (mWpsStarted) {
-                WifiConfigStore.enableAllNetworks();
-                WifiConfigStore.loadConfiguredNetworks();
-                mWpsStarted = false;
-            }
             EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+            mRssiPollToken++;
+            if (mEnableRssiPolling) {
+                sendMessage(obtainMessage(WifiStateMachine.CMD_RSSI_POLL, mRssiPollToken, 0));
+            }
         }
         @Override
         public boolean processMessage(Message message) {
@@ -2650,6 +2647,15 @@
                         deferMessage(message);
                     }
                     break;
+                case CMD_START_SCAN:
+                    /* When the network is connected, re-scanning can trigger
+                     * a reconnection. Put it in scan-only mode during scan.
+                     * When scan results are received, the mode is switched
+                     * back to CONNECT_MODE.
+                     */
+                    WifiNative.setScanResultHandlingCommand(SCAN_ONLY_MODE);
+                    WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE);
+                    break;
                     /* Ignore connection to same network */
                 case CMD_CONNECT_NETWORK:
                     int netId = message.arg1;
@@ -2660,6 +2666,26 @@
                     /* Ignore */
                 case NETWORK_CONNECTION_EVENT:
                     break;
+                case CMD_RSSI_POLL:
+                    if (message.arg1 == mRssiPollToken) {
+                        // Get Info and continue polling
+                        fetchRssiAndLinkSpeedNative();
+                        sendMessageDelayed(obtainMessage(WifiStateMachine.CMD_RSSI_POLL,
+                                mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS);
+                    } else {
+                        // Polling has completed
+                    }
+                    break;
+                case CMD_ENABLE_RSSI_POLL:
+                    mEnableRssiPolling = (message.arg1 == 1);
+                    mRssiPollToken++;
+                    if (mEnableRssiPolling) {
+                        // first poll
+                        fetchRssiAndLinkSpeedNative();
+                        sendMessageDelayed(obtainMessage(WifiStateMachine.CMD_RSSI_POLL,
+                                mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS);
+                    }
+                    break;
                 default:
                     return NOT_HANDLED;
             }
@@ -2686,6 +2712,10 @@
                         deferMessage(message);
                     }
                     break;
+                    /* Handle in  DisconnectedState */
+                case SUPPLICANT_STATE_CHANGE_EVENT:
+                    deferMessage(message);
+                    break;
                 default:
                     return NOT_HANDLED;
             }
@@ -2734,6 +2764,12 @@
                     /* Ignore network disconnect */
                 case NETWORK_DISCONNECTION_EVENT:
                     break;
+                case SUPPLICANT_STATE_CHANGE_EVENT:
+                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
+                    SupplicantState state = (SupplicantState) stateChangeResult.state;
+                    setDetailedState(WifiInfo.getDetailedStateOf(state));
+                    /* DriverStartedState does the rest of the handling */
+                    return NOT_HANDLED;
                 default:
                     return NOT_HANDLED;
             }
@@ -2795,375 +2831,4 @@
             return HANDLED;
         }
     }
-
-
-    class SupplicantStateTracker extends HierarchicalStateMachine {
-
-        private int mRssiPollToken = 0;
-
-        /**
-         * The max number of the WPA supplicant loop iterations before we
-         * decide that the loop should be terminated:
-         */
-        private static final int MAX_SUPPLICANT_LOOP_ITERATIONS = 4;
-        private int mLoopDetectIndex = 0;
-        private int mLoopDetectCount = 0;
-
-        /**
-         *  Supplicant state change commands follow
-         *  the ordinal values defined in SupplicantState.java
-         */
-        private static final int DISCONNECTED           = 0;
-        private static final int INACTIVE               = 1;
-        private static final int SCANNING               = 2;
-        private static final int ASSOCIATING            = 3;
-        private static final int ASSOCIATED             = 4;
-        private static final int FOUR_WAY_HANDSHAKE     = 5;
-        private static final int GROUP_HANDSHAKE        = 6;
-        private static final int COMPLETED              = 7;
-        private static final int DORMANT                = 8;
-        private static final int UNINITIALIZED          = 9;
-        private static final int INVALID                = 10;
-
-        private HierarchicalState mUninitializedState = new UninitializedState();
-        private HierarchicalState mInitializedState = new InitializedState();;
-        private HierarchicalState mInactiveState = new InactiveState();
-        private HierarchicalState mDisconnectState = new DisconnectedState();
-        private HierarchicalState mScanState = new ScanState();
-        private HierarchicalState mConnectState = new ConnectState();
-        private HierarchicalState mHandshakeState = new HandshakeState();
-        private HierarchicalState mCompletedState = new CompletedState();
-        private HierarchicalState mDormantState = new DormantState();
-
-        public SupplicantStateTracker(Context context, Handler target) {
-            super(TAG, target.getLooper());
-
-            addState(mUninitializedState);
-            addState(mInitializedState);
-                addState(mInactiveState, mInitializedState);
-                addState(mDisconnectState, mInitializedState);
-                addState(mScanState, mInitializedState);
-                addState(mConnectState, mInitializedState);
-                    addState(mHandshakeState, mConnectState);
-                    addState(mCompletedState, mConnectState);
-                addState(mDormantState, mInitializedState);
-
-            setInitialState(mUninitializedState);
-
-            //start the state machine
-            start();
-        }
-
-        public void handleEvent(StateChangeResult stateChangeResult) {
-            SupplicantState newState = (SupplicantState) stateChangeResult.state;
-
-            // Supplicant state change
-            // [31-13] Reserved for future use
-            // [8 - 0] Supplicant state (as defined in SupplicantState.java)
-            // 50023 supplicant_state_changed (custom|1|5)
-            EventLog.writeEvent(EVENTLOG_SUPPLICANT_STATE_CHANGED, newState.ordinal());
-
-            sendMessage(obtainMessage(newState.ordinal(), stateChangeResult));
-        }
-
-        public void resetSupplicantState() {
-            transitionTo(mUninitializedState);
-        }
-
-        private void resetLoopDetection() {
-            mLoopDetectCount = 0;
-            mLoopDetectIndex = 0;
-        }
-
-        private boolean handleTransition(Message msg) {
-            if (DBG) Log.d(TAG, getName() + msg.toString() + "\n");
-            switch (msg.what) {
-                case DISCONNECTED:
-                    transitionTo(mDisconnectState);
-                    break;
-                case SCANNING:
-                    transitionTo(mScanState);
-                    break;
-                case ASSOCIATING:
-                    StateChangeResult stateChangeResult = (StateChangeResult) msg.obj;
-                    /* BSSID is valid only in ASSOCIATING state */
-                    mWifiInfo.setBSSID(stateChangeResult.BSSID);
-                    //$FALL-THROUGH$
-                case ASSOCIATED:
-                case FOUR_WAY_HANDSHAKE:
-                case GROUP_HANDSHAKE:
-                    transitionTo(mHandshakeState);
-                    break;
-                case COMPLETED:
-                    transitionTo(mCompletedState);
-                    break;
-                case DORMANT:
-                    transitionTo(mDormantState);
-                    break;
-                case INACTIVE:
-                    transitionTo(mInactiveState);
-                    break;
-                case UNINITIALIZED:
-                case INVALID:
-                    transitionTo(mUninitializedState);
-                    break;
-                default:
-                    return NOT_HANDLED;
-            }
-            StateChangeResult stateChangeResult = (StateChangeResult) msg.obj;
-            SupplicantState supState = (SupplicantState) stateChangeResult.state;
-            setDetailedState(WifiInfo.getDetailedStateOf(supState));
-            mWifiInfo.setSupplicantState(supState);
-            mWifiInfo.setNetworkId(stateChangeResult.networkId);
-            return HANDLED;
-        }
-
-        /********************************************************
-         * HSM states
-         *******************************************************/
-
-        class InitializedState extends HierarchicalState {
-            @Override
-             public void enter() {
-                 if (DBG) Log.d(TAG, getName() + "\n");
-             }
-            @Override
-            public boolean processMessage(Message message) {
-                if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
-                switch (message.what) {
-                    case CMD_START_SCAN:
-                        WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE);
-                        break;
-                    default:
-                        if (DBG) Log.w(TAG, "Ignoring " + message);
-                        break;
-                }
-                return HANDLED;
-            }
-        }
-
-        class UninitializedState extends HierarchicalState {
-            @Override
-             public void enter() {
-                 if (DBG) Log.d(TAG, getName() + "\n");
-                 mNetworkInfo.setIsAvailable(false);
-                 resetLoopDetection();
-                 mPasswordKeyMayBeIncorrect = false;
-             }
-            @Override
-            public boolean processMessage(Message message) {
-                switch(message.what) {
-                    default:
-                        if (!handleTransition(message)) {
-                            if (DBG) Log.w(TAG, "Ignoring " + message);
-                        }
-                        break;
-                }
-                return HANDLED;
-            }
-            @Override
-            public void exit() {
-                mNetworkInfo.setIsAvailable(true);
-            }
-        }
-
-        class InactiveState extends HierarchicalState {
-            @Override
-             public void enter() {
-                 if (DBG) Log.d(TAG, getName() + "\n");
-
-                 /* A failed WPS connection */
-                 if (mWpsStarted) {
-                     Log.e(TAG, "WPS set up failed, enabling other networks");
-                     WifiConfigStore.enableAllNetworks();
-                     mWpsStarted = false;
-                 }
-
-                 Message message = getCurrentMessage();
-                 StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
-
-                 mNetworkInfo.setIsAvailable(false);
-                 resetLoopDetection();
-                 mPasswordKeyMayBeIncorrect = false;
-
-                 sendSupplicantStateChangedBroadcast(stateChangeResult, false);
-             }
-            @Override
-            public boolean processMessage(Message message) {
-                return handleTransition(message);
-            }
-            @Override
-            public void exit() {
-                mNetworkInfo.setIsAvailable(true);
-            }
-        }
-
-
-        class DisconnectedState extends HierarchicalState {
-            @Override
-             public void enter() {
-                 if (DBG) Log.d(TAG, getName() + "\n");
-                 Message message = getCurrentMessage();
-                 StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
-
-                 resetLoopDetection();
-
-                 /* If a disconnect event happens after a password key failure
-                  * event, disable the network
-                  */
-                 if (mPasswordKeyMayBeIncorrect) {
-                     Log.d(TAG, "Failed to authenticate, disabling network " +
-                             mWifiInfo.getNetworkId());
-                     WifiConfigStore.disableNetwork(mWifiInfo.getNetworkId());
-                     mPasswordKeyMayBeIncorrect = false;
-                     sendSupplicantStateChangedBroadcast(stateChangeResult, true);
-                 }
-                 else {
-                     sendSupplicantStateChangedBroadcast(stateChangeResult, false);
-                 }
-             }
-            @Override
-            public boolean processMessage(Message message) {
-                return handleTransition(message);
-            }
-        }
-
-        class ScanState extends HierarchicalState {
-            @Override
-             public void enter() {
-                 if (DBG) Log.d(TAG, getName() + "\n");
-                 Message message = getCurrentMessage();
-                 StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
-
-                 mPasswordKeyMayBeIncorrect = false;
-                 resetLoopDetection();
-                 sendSupplicantStateChangedBroadcast(stateChangeResult, false);
-             }
-            @Override
-            public boolean processMessage(Message message) {
-                return handleTransition(message);
-            }
-        }
-
-        class ConnectState extends HierarchicalState {
-            @Override
-             public void enter() {
-                 if (DBG) Log.d(TAG, getName() + "\n");
-             }
-            @Override
-            public boolean processMessage(Message message) {
-                switch (message.what) {
-                    case CMD_START_SCAN:
-                        WifiNative.setScanResultHandlingCommand(SCAN_ONLY_MODE);
-                        WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE);
-                        break;
-                    default:
-                        return NOT_HANDLED;
-                }
-                return HANDLED;
-            }
-        }
-
-        class HandshakeState extends HierarchicalState {
-            @Override
-             public void enter() {
-                 if (DBG) Log.d(TAG, getName() + "\n");
-                 final Message message = getCurrentMessage();
-                 StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
-
-                 if (mLoopDetectIndex > message.what) {
-                     mLoopDetectCount++;
-                 }
-                 if (mLoopDetectCount > MAX_SUPPLICANT_LOOP_ITERATIONS) {
-                     WifiConfigStore.disableNetwork(stateChangeResult.networkId);
-                     mLoopDetectCount = 0;
-                 }
-
-                 mLoopDetectIndex = message.what;
-
-                 mPasswordKeyMayBeIncorrect = false;
-                 sendSupplicantStateChangedBroadcast(stateChangeResult, false);
-             }
-            @Override
-            public boolean processMessage(Message message) {
-                return handleTransition(message);
-            }
-        }
-
-        class CompletedState extends HierarchicalState {
-            @Override
-             public void enter() {
-                 if (DBG) Log.d(TAG, getName() + "\n");
-                 Message message = getCurrentMessage();
-                 StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
-
-                 mRssiPollToken++;
-                 if (mEnableRssiPolling) {
-                     sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0),
-                             POLL_RSSI_INTERVAL_MSECS);
-                 }
-
-                 resetLoopDetection();
-
-                 mPasswordKeyMayBeIncorrect = false;
-                 sendSupplicantStateChangedBroadcast(stateChangeResult, false);
-             }
-            @Override
-            public boolean processMessage(Message message) {
-                switch(message.what) {
-                    case ASSOCIATING:
-                    case ASSOCIATED:
-                    case FOUR_WAY_HANDSHAKE:
-                    case GROUP_HANDSHAKE:
-                    case COMPLETED:
-                        break;
-                    case CMD_RSSI_POLL:
-                        if (message.arg1 == mRssiPollToken) {
-                            // Get Info and continue polling
-                            requestPolledInfo();
-                            sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0),
-                                    POLL_RSSI_INTERVAL_MSECS);
-                        } else {
-                            // Polling has completed
-                        }
-                        break;
-                    case CMD_ENABLE_RSSI_POLL:
-                        mRssiPollToken++;
-                        if (mEnableRssiPolling) {
-                            // first poll
-                            requestPolledInfo();
-                            sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0),
-                                    POLL_RSSI_INTERVAL_MSECS);
-                        }
-                        break;
-                    default:
-                        return handleTransition(message);
-                }
-                return HANDLED;
-            }
-        }
-
-        class DormantState extends HierarchicalState {
-            @Override
-            public void enter() {
-                if (DBG) Log.d(TAG, getName() + "\n");
-                Message message = getCurrentMessage();
-                StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
-
-                resetLoopDetection();
-                mPasswordKeyMayBeIncorrect = false;
-
-                sendSupplicantStateChangedBroadcast(stateChangeResult, false);
-
-                /* TODO: reconnect is now being handled at DHCP failure handling
-                 * If we run into issues with staying in Dormant state, might
-                 * need a reconnect here
-                 */
-            }
-            @Override
-            public boolean processMessage(Message message) {
-                return handleTransition(message);
-            }
-        }
-    }
 }