diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
new file mode 100644
index 0000000..11f34cc
--- /dev/null
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -0,0 +1,693 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.ConnectivityManager;
+import android.net.IConnectivityManager;
+import android.net.MobileDataStateTracker;
+import android.net.NetworkInfo;
+import android.net.NetworkStateTracker;
+import android.net.wifi.WifiStateTracker;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.ServiceManager;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.telephony.TelephonyManager;
+import android.util.EventLog;
+import android.util.Log;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * {@hide}
+ */
+public class ConnectivityService extends IConnectivityManager.Stub {
+
+    private static final boolean DBG = false;
+    private static final String TAG = "ConnectivityService";
+
+    // Event log tags (must be in sync with event-log-tags)
+    private static final int EVENTLOG_CONNECTIVITY_STATE_CHANGED = 50020;
+
+    /**
+     * Sometimes we want to refer to the individual network state
+     * trackers separately, and sometimes we just want to treat them
+     * abstractly.
+     */
+    private NetworkStateTracker mNetTrackers[];
+    private boolean mTeardownRequested[];
+    private WifiStateTracker mWifiStateTracker;
+    private MobileDataStateTracker mMobileDataStateTracker;
+    private WifiWatchdogService mWifiWatchdogService;
+
+    private Context mContext;
+    private int mNetworkPreference;
+    private NetworkStateTracker mActiveNetwork;
+
+    private int mNumDnsEntries;
+    private static int mDnsChangeCounter;
+
+    private boolean mTestMode;
+    private static ConnectivityService sServiceInstance;
+    
+    private static class ConnectivityThread extends Thread {
+        private Context mContext;
+        
+        private ConnectivityThread(Context context) {
+            super("ConnectivityThread");
+            mContext = context;
+        }
+
+        @Override
+        public void run() {
+            Looper.prepare();
+            synchronized (this) {
+                sServiceInstance = new ConnectivityService(mContext);
+                notifyAll();
+            }
+            Looper.loop();
+        }
+        
+        public static ConnectivityService getServiceInstance(Context context) {
+            ConnectivityThread thread = new ConnectivityThread(context);
+            thread.start();
+            
+            synchronized (thread) {
+                while (sServiceInstance == null) {
+                    try {
+                        // Wait until sServiceInstance has been initialized.
+                        thread.wait();
+                    } catch (InterruptedException e) {
+                    }
+                }
+            }
+            
+            return sServiceInstance;
+        }
+    }
+    
+    public static ConnectivityService getInstance(Context context) {
+        return ConnectivityThread.getServiceInstance(context);
+    }
+    
+    private ConnectivityService(Context context) {
+        if (DBG) Log.v(TAG, "ConnectivityService starting up");
+        mContext = context;
+        mNetTrackers = new NetworkStateTracker[2];
+        mTeardownRequested = new boolean[2];
+        Handler handler = new MyHandler();
+        
+        mNetworkPreference = getPersistedNetworkPreference();
+                
+        /*
+         * Create the network state trackers for Wi-Fi and mobile
+         * data. Maybe this could be done with a factory class,
+         * but it's not clear that it's worth it, given that
+         * the number of different network types is not going
+         * to change very often.
+         */
+        if (DBG) Log.v(TAG, "Starting Wifi Service.");
+        mWifiStateTracker = new WifiStateTracker(context, handler);
+        WifiService wifiService = new WifiService(context, mWifiStateTracker);
+        ServiceManager.addService(Context.WIFI_SERVICE, wifiService);
+        // The WifiStateTracker should appear first in the list
+        mNetTrackers[ConnectivityManager.TYPE_WIFI] = mWifiStateTracker;
+
+        mMobileDataStateTracker = new MobileDataStateTracker(context, handler);
+        mNetTrackers[ConnectivityManager.TYPE_MOBILE] = mMobileDataStateTracker;
+        
+        mActiveNetwork = null;
+        mNumDnsEntries = 0;
+
+        mTestMode = SystemProperties.get("cm.test.mode").equals("true")
+                && SystemProperties.get("ro.build.type").equals("eng");
+
+        for (NetworkStateTracker t : mNetTrackers)
+            t.startMonitoring();
+
+        // Constructing this starts it too
+        mWifiWatchdogService = new WifiWatchdogService(context, mWifiStateTracker);
+    }
+
+    /**
+     * Sets the preferred network. 
+     * @param preference the new preference
+     */
+    public synchronized void setNetworkPreference(int preference) {
+        enforceChangePermission();
+        if (ConnectivityManager.isNetworkTypeValid(preference)) {
+            int oldPreference = mNetworkPreference;
+            persistNetworkPreference(preference);
+            if (mNetworkPreference != oldPreference)
+                enforcePreference();
+        }
+    }
+
+    public int getNetworkPreference() {
+        enforceAccessPermission();
+        return mNetworkPreference;
+    }
+
+    private void persistNetworkPreference(int networkPreference) {
+        final ContentResolver cr = mContext.getContentResolver();
+        Settings.System.putInt(cr, Settings.System.NETWORK_PREFERENCE, networkPreference);
+    }
+    
+    private int getPersistedNetworkPreference() {
+        final ContentResolver cr = mContext.getContentResolver();
+
+        final int networkPrefSetting = Settings.System
+                .getInt(cr, Settings.System.NETWORK_PREFERENCE, -1);
+        if (networkPrefSetting != -1) {
+            return networkPrefSetting;
+        }
+
+        return ConnectivityManager.DEFAULT_NETWORK_PREFERENCE;
+    }
+    
+    /**
+     * Make the state of network connectivity conform to the preference settings.
+     * In this method, we only tear down a non-preferred network. Establishing
+     * a connection to the preferred network is taken care of when we handle
+     * the disconnect event from the non-preferred network
+     * (see {@link #handleDisconnect(NetworkInfo)}).
+     */
+    private void enforcePreference() {
+        if (mActiveNetwork == null)
+            return;
+
+        for (NetworkStateTracker t : mNetTrackers) {
+            if (t == mActiveNetwork) {
+                int netType = t.getNetworkInfo().getType();
+                int otherNetType = ((netType == ConnectivityManager.TYPE_WIFI) ?
+                        ConnectivityManager.TYPE_MOBILE :
+                        ConnectivityManager.TYPE_WIFI);
+
+                if (t.getNetworkInfo().getType() != mNetworkPreference) {
+                    NetworkStateTracker otherTracker = mNetTrackers[otherNetType];
+                    if (otherTracker.isAvailable()) {
+                        teardown(t);
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean teardown(NetworkStateTracker netTracker) {
+        if (netTracker.teardown()) {
+            mTeardownRequested[netTracker.getNetworkInfo().getType()] = true;
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Return NetworkInfo for the active network interface. It is assumed that at most
+     * one network is active at a time. If more than one is active, it is indeterminate
+     * which will be returned.
+     * @return the info for the active network, or {@code null} if none is active
+     */
+    public NetworkInfo getActiveNetworkInfo() {
+        enforceAccessPermission();
+        for (NetworkStateTracker t : mNetTrackers) {
+            NetworkInfo info = t.getNetworkInfo();
+            if (info.isConnected()) {
+                return info;
+            }
+        }
+        return null;
+    }
+
+    public NetworkInfo getNetworkInfo(int networkType) {
+        enforceAccessPermission();
+        if (ConnectivityManager.isNetworkTypeValid(networkType)) {
+            NetworkStateTracker t = mNetTrackers[networkType];
+            if (t != null)
+                return t.getNetworkInfo();
+        }
+        return null;
+    }
+
+    public NetworkInfo[] getAllNetworkInfo() {
+        enforceAccessPermission();
+        NetworkInfo[] result = new NetworkInfo[mNetTrackers.length];
+        int i = 0;
+        for (NetworkStateTracker t : mNetTrackers) {
+            result[i++] = t.getNetworkInfo();
+        }
+        return result;
+    }
+
+    public boolean setRadios(boolean turnOn) {
+        boolean result = true;
+        enforceChangePermission();
+        for (NetworkStateTracker t : mNetTrackers) {
+            result = t.setRadio(turnOn) && result;
+        }
+        return result;
+    }
+
+    public boolean setRadio(int netType, boolean turnOn) {
+        enforceChangePermission();
+        if (!ConnectivityManager.isNetworkTypeValid(netType)) {
+            return false;
+        }
+        NetworkStateTracker tracker = mNetTrackers[netType];
+        return tracker != null && tracker.setRadio(turnOn);
+    }
+
+    public int startUsingNetworkFeature(int networkType, String feature) {
+        enforceChangePermission();
+        if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
+            return -1;
+        }
+        NetworkStateTracker tracker = mNetTrackers[networkType];
+        if (tracker != null) {
+            return tracker.startUsingNetworkFeature(feature, getCallingPid(), getCallingUid());
+        }
+        return -1;
+
+    }
+
+    public int stopUsingNetworkFeature(int networkType, String feature) {
+        enforceChangePermission();
+        if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
+            return -1;
+        }
+        NetworkStateTracker tracker = mNetTrackers[networkType];
+        if (tracker != null) {
+            return tracker.stopUsingNetworkFeature(feature, getCallingPid(), getCallingUid());
+        }
+        return -1;
+    }
+
+    /**
+     * Ensure that a network route exists to deliver traffic to the specified
+     * host via the specified network interface.
+     * @param networkType the type of the network over which traffic to the specified
+     * host is to be routed
+     * @param hostAddress the IP address of the host to which the route is desired
+     * @return {@code true} on success, {@code false} on failure
+     */
+    public boolean requestRouteToHost(int networkType, int hostAddress) {
+        enforceChangePermission();
+        if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
+            return false;
+        }
+        NetworkStateTracker tracker = mNetTrackers[networkType];
+        /*
+         * If there's only one connected network, and it's the one requested,
+         * then we don't have to do anything - the requested route already
+         * exists. If it's not the requested network, then it's not possible
+         * to establish the requested route. Finally, if there is more than
+         * one connected network, then we must insert an entry in the routing
+         * table.
+         */
+        if (getNumConnectedNetworks() > 1) {
+            return tracker.requestRouteToHost(hostAddress);
+        } else {
+            return tracker.getNetworkInfo().getType() == networkType;
+        }
+    }
+
+    private int getNumConnectedNetworks() {
+        int numConnectedNets = 0;
+
+        for (NetworkStateTracker nt : mNetTrackers) {
+            if (nt.getNetworkInfo().isConnected()
+                    && !mTeardownRequested[nt.getNetworkInfo().getType()]) {
+                ++numConnectedNets;
+            }
+        }
+        return numConnectedNets;
+    }
+
+    private void enforceAccessPermission() {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
+                                          "ConnectivityService");
+    }
+
+    private void enforceChangePermission() {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_NETWORK_STATE,
+                                          "ConnectivityService");
+
+    }
+
+    /**
+     * Handle a {@code DISCONNECTED} event. If this pertains to the non-active network,
+     * we ignore it. If it is for the active network, we send out a broadcast.
+     * But first, we check whether it might be possible to connect to a different
+     * network.
+     * @param info the {@code NetworkInfo} for the network
+     */
+    private void handleDisconnect(NetworkInfo info) {
+
+        if (DBG) Log.v(TAG, "Handle DISCONNECT for " + info.getTypeName());
+
+        /*
+         * If the disconnected network is not the active one, then don't report
+         * this as a loss of connectivity. What probably happened is that we're
+         * getting the disconnect for a network that we explicitly disabled
+         * in accordance with network preference policies.
+         */
+        mTeardownRequested[info.getType()] = false;
+        if (mActiveNetwork == null ||  info.getType() != mActiveNetwork.getNetworkInfo().getType())
+            return;
+
+        NetworkStateTracker newNet;
+        if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
+            newNet = mWifiStateTracker;
+        } else /* info().getType() == TYPE_WIFI */ {
+            newNet = mMobileDataStateTracker;
+        }
+
+        NetworkInfo switchTo = null;
+        if (newNet.isAvailable()) {
+            mActiveNetwork = newNet;
+            switchTo = newNet.getNetworkInfo();
+            switchTo.setFailover(true);
+            if (!switchTo.isConnectedOrConnecting())
+                newNet.reconnect();
+        }
+
+        boolean otherNetworkConnected = false;
+        Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
+        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
+        if (info.isFailover()) {
+            intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
+            info.setFailover(false);
+        }
+        if (info.getReason() != null) {
+            intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
+        }
+        if (info.getExtraInfo() != null) {
+            intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, info.getExtraInfo());
+        }
+        if (switchTo != null) {
+            otherNetworkConnected = switchTo.isConnected();
+            if (DBG) {
+                if (otherNetworkConnected) {
+                    Log.v(TAG, "Switching to already connected " + switchTo.getTypeName());
+                } else {
+                    Log.v(TAG, "Attempting to switch to " + switchTo.getTypeName());
+                }
+            }
+            intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
+        } else {
+            intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
+        }
+        if (DBG) Log.v(TAG, "Sending DISCONNECT bcast for " + info.getTypeName() +
+                (switchTo == null ? "" : " other=" + switchTo.getTypeName()));
+
+        mContext.sendStickyBroadcast(intent);
+        /*
+         * If the failover network is already connected, then immediately send out
+         * a followup broadcast indicating successful failover
+         */
+        if (switchTo != null && otherNetworkConnected)
+            sendConnectedBroadcast(switchTo);
+    }
+
+    private void sendConnectedBroadcast(NetworkInfo info) {
+        Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
+        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
+        if (info.isFailover()) {
+            intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
+            info.setFailover(false);
+        }
+        if (info.getReason() != null) {
+            intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
+        }
+        if (info.getExtraInfo() != null) {
+            intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, info.getExtraInfo());
+        }
+        mContext.sendStickyBroadcast(intent);
+    }
+
+    private void handleConnectionFailure(NetworkInfo info) {
+        mTeardownRequested[info.getType()] = false;
+        if (getActiveNetworkInfo() == null) {
+            String reason = info.getReason();
+            String extraInfo = info.getExtraInfo();
+
+            if (DBG) {
+                String reasonText;
+                if (reason == null) {
+                    reasonText = ".";
+                } else {
+                    reasonText = " (" + reason + ").";
+                }
+                Log.v(TAG, "Attempt to connect to " + info.getTypeName() + " failed" + reasonText);
+            }
+            
+            Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
+            intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
+            intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
+            if (reason != null) {
+                intent.putExtra(ConnectivityManager.EXTRA_REASON, reason);
+            }
+            if (extraInfo != null) {
+                intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, extraInfo);
+            }
+            if (info.isFailover()) {
+                intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
+                info.setFailover(false);
+            }
+            mContext.sendStickyBroadcast(intent);
+        }
+    }
+
+    private void handleConnect(NetworkInfo info) {
+        if (DBG) Log.v(TAG, "Handle CONNECT for " + info.getTypeName());
+
+        // snapshot isFailover, because sendConnectedBroadcast() resets it
+        boolean isFailover = info.isFailover();
+        NetworkStateTracker thisNet = mNetTrackers[info.getType()];
+        NetworkStateTracker deadnet = null;
+        NetworkStateTracker otherNet;
+        if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
+            otherNet = mWifiStateTracker;
+        } else /* info().getType() == TYPE_WIFI */ {
+            otherNet = mMobileDataStateTracker;
+        }
+        /*
+        * Check policy to see whether we are now connected to a network that
+        * takes precedence over the other one. If so, we need to tear down
+        * the other one.
+        */
+        NetworkInfo wifiInfo = mWifiStateTracker.getNetworkInfo();
+        NetworkInfo mobileInfo = mMobileDataStateTracker.getNetworkInfo();
+        if (wifiInfo.isConnected() && mobileInfo.isConnected()) {
+            if (mNetworkPreference == ConnectivityManager.TYPE_WIFI)
+                deadnet = mMobileDataStateTracker;
+            else
+                deadnet = mWifiStateTracker;
+        }
+
+        boolean toredown = false;
+        mTeardownRequested[info.getType()] = false;
+        if (!mTestMode && deadnet != null) {
+            if (DBG) Log.v(TAG, "Policy requires " +
+                  deadnet.getNetworkInfo().getTypeName() + " teardown");
+            toredown = teardown(deadnet);
+            if (DBG && !toredown) {
+                Log.d(TAG, "Network declined teardown request");
+            }
+        }
+
+        if (!toredown || deadnet.getNetworkInfo().getType() != info.getType()) {
+            mActiveNetwork = thisNet;
+            if (DBG) Log.v(TAG, "Sending CONNECT bcast for " + info.getTypeName());
+            thisNet.updateNetworkSettings();
+            sendConnectedBroadcast(info);
+            if (isFailover) {
+                otherNet.releaseWakeLock();
+            }
+        } else {
+            if (DBG) Log.v(TAG, "Not broadcasting CONNECT_ACTION to torn down network " +
+                info.getTypeName());
+        }
+    }
+
+    private void handleScanResultsAvailable(NetworkInfo info) {
+        int networkType = info.getType();
+        if (networkType != ConnectivityManager.TYPE_WIFI) {
+            if (DBG) Log.v(TAG, "Got ScanResultsAvailable for " + info.getTypeName() + " network."
+                + " Don't know how to handle.");
+        }
+        
+        mNetTrackers[networkType].interpretScanResultsAvailable();
+    }
+
+    private void handleNotificationChange(boolean visible, int id, Notification notification) {
+        NotificationManager notificationManager = (NotificationManager) mContext
+                .getSystemService(Context.NOTIFICATION_SERVICE);
+        
+        if (visible) {
+            notificationManager.notify(id, notification);
+        } else {
+            notificationManager.cancel(id);
+        }
+    }
+
+    /**
+     * After any kind of change in the connectivity state of any network,
+     * make sure that anything that depends on the connectivity state of
+     * more than one network is set up correctly. We're mainly concerned
+     * with making sure that the list of DNS servers is set up  according
+     * to which networks are connected, and ensuring that the right routing
+     * table entries exist.
+     */
+    private void handleConnectivityChange() {
+        /*
+         * If both mobile and wifi are enabled, add the host routes that
+         * will allow MMS traffic to pass on the mobile network. But
+         * remove the default route for the mobile network, so that there
+         * will be only one default route, to ensure that all traffic
+         * except MMS will travel via Wi-Fi.
+         */
+        int numConnectedNets = handleConfigurationChange();
+        if (numConnectedNets > 1) {
+            mMobileDataStateTracker.addPrivateRoutes();
+            mMobileDataStateTracker.removeDefaultRoute();
+        } else if (mMobileDataStateTracker.getNetworkInfo().isConnected()) {
+            mMobileDataStateTracker.removePrivateRoutes();
+            mMobileDataStateTracker.restoreDefaultRoute();
+        }
+    }
+
+    private int handleConfigurationChange() {
+        /*
+         * Set DNS properties. Always put Wi-Fi entries at the front of
+         * the list if it is active.
+         */
+        int index = 1;
+        String lastDns = "";
+        int numConnectedNets = 0;
+        int incrValue = ConnectivityManager.TYPE_MOBILE - ConnectivityManager.TYPE_WIFI;
+        int stopValue = ConnectivityManager.TYPE_MOBILE + incrValue;
+
+        for (int net = ConnectivityManager.TYPE_WIFI; net != stopValue; net += incrValue) {            
+            NetworkStateTracker nt = mNetTrackers[net];
+            if (nt.getNetworkInfo().isConnected()
+                    && !mTeardownRequested[nt.getNetworkInfo().getType()]) {
+                ++numConnectedNets;
+                String[] dnsList = nt.getNameServers();
+                for (int i = 0; i < dnsList.length && dnsList[i] != null; i++) {
+                    // skip duplicate entries
+                    if (!dnsList[i].equals(lastDns)) {
+                        SystemProperties.set("net.dns" + index++, dnsList[i]);
+                        lastDns = dnsList[i];
+                    }
+                }
+            }
+        }
+        // Null out any DNS properties that are no longer used
+        for (int i = index; i <= mNumDnsEntries; i++) {
+            SystemProperties.set("net.dns" + i, "");
+        }
+        mNumDnsEntries = index - 1;
+        // Notify the name resolver library of the change
+        SystemProperties.set("net.dnschange", String.valueOf(mDnsChangeCounter++));
+        return numConnectedNets;
+    }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mContext.checkCallingPermission(android.Manifest.permission.DUMP)
+                != PackageManager.PERMISSION_GRANTED) {
+            pw.println("Permission Denial: can't dump ConnectivityService from from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid());
+            return;
+        }
+        if (mActiveNetwork == null) {
+            pw.println("No active network");
+        } else {
+            pw.println("Active network: " + mActiveNetwork.getNetworkInfo().getTypeName());
+        }
+        pw.println();
+        for (NetworkStateTracker nst : mNetTrackers) {
+            pw.println(nst.getNetworkInfo());
+            pw.println(nst);
+            pw.println();
+        }
+    }
+
+    private class MyHandler extends Handler {
+        @Override
+        public void handleMessage(Message msg) {
+            NetworkInfo info;
+            switch (msg.what) {
+                case NetworkStateTracker.EVENT_STATE_CHANGED:
+                    info = (NetworkInfo) msg.obj;
+                    if (DBG) Log.v(TAG, "ConnectivityChange for " + info.getTypeName() + ": " +
+                            info.getState() + "/" + info.getDetailedState());
+
+                    // Connectivity state changed:
+                    // [31-11] Reserved for future use
+                    // [10-9] Mobile network connection type (as defined by the TelephonyManager)
+                    // [8-3] Detailed state ordinal (as defined by NetworkInfo.DetailedState)   
+                    // [2-0] Network type (as defined by ConnectivityManager)
+                    int eventLogParam = (info.getType() & 0x7) |
+                         ((info.getDetailedState().ordinal() & 0x3f) << 3) |
+                         (TelephonyManager.getDefault().getNetworkType() << 9);
+                    EventLog.writeEvent(EVENTLOG_CONNECTIVITY_STATE_CHANGED, eventLogParam);
+                    
+                    if (info.getDetailedState() == NetworkInfo.DetailedState.FAILED) {
+                        handleConnectionFailure(info);
+                    } else if (info.getState() == NetworkInfo.State.DISCONNECTED) {
+                        handleDisconnect(info);
+                    } else if (info.getState() == NetworkInfo.State.SUSPENDED) {
+                        // TODO: need to think this over.
+                        // the logic here is, handle SUSPENDED the same as DISCONNECTED. The
+                        // only difference being we are broadcasting an intent with NetworkInfo
+                        // that's suspended. This allows the applications an opportunity to
+                        // handle DISCONNECTED and SUSPENDED differently, or not.
+                        handleDisconnect(info);
+                    } else if (info.getState() == NetworkInfo.State.CONNECTED) {
+                        handleConnect(info);
+                    }
+                    handleConnectivityChange();
+                    break;
+
+                case NetworkStateTracker.EVENT_SCAN_RESULTS_AVAILABLE:
+                    info = (NetworkInfo) msg.obj;
+                    handleScanResultsAvailable(info);
+                    break;
+                    
+                case NetworkStateTracker.EVENT_NOTIFICATION_CHANGED:
+                    handleNotificationChange(msg.arg1 == 1, msg.arg2, (Notification) msg.obj);
+
+                case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
+                    handleConfigurationChange();
+                    break;
+            }
+        }
+    }
+}
