diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
new file mode 100644
index 0000000..760988d
--- /dev/null
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -0,0 +1,741 @@
+/*
+ * 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.provider.Sync;
+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 WifiStateTracker mWifiStateTracker;
+    private MobileDataStateTracker mMobileDataStateTracker;
+    private WifiWatchdogService mWifiWatchdogService;
+
+    private Context mContext;
+    private int mNetworkPreference;
+    private NetworkStateTracker mActiveNetwork;
+
+    private int mNumDnsEntries;
+    private static int sDnsChangeCounter;
+
+    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 ignore) {
+                        Log.e(TAG,
+                            "Unexpected InterruptedException while waiting for ConnectivityService thread");
+                    }
+                }
+            }
+            
+            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];
+        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);
+        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)) {
+            if (mNetworkPreference != preference) {
+                persistNetworkPreference(preference);
+                mNetworkPreference = preference;
+                enforcePreference();
+            }
+        }
+    }
+
+    public int getNetworkPreference() {
+        enforceAccessPermission();
+        return mNetworkPreference;
+    }
+
+    private void persistNetworkPreference(int networkPreference) {
+        final ContentResolver cr = mContext.getContentResolver();
+        Settings.Secure.putInt(cr, Settings.Secure.NETWORK_PREFERENCE, networkPreference);
+    }
+    
+    private int getPersistedNetworkPreference() {
+        final ContentResolver cr = mContext.getContentResolver();
+
+        final int networkPrefSetting = Settings.Secure
+                .getInt(cr, Settings.Secure.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()) {
+            netTracker.setTeardownRequested(true);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Return NetworkInfo for the active (i.e., connected) 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;
+        }
+    }
+
+    /**
+     * @see ConnectivityManager#getBackgroundDataSetting()
+     */
+    public boolean getBackgroundDataSetting() {
+        return Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.BACKGROUND_DATA, 1) == 1;
+    }
+    
+    /**
+     * @see ConnectivityManager#setBackgroundDataSetting(boolean)
+     */
+    public void setBackgroundDataSetting(boolean allowBackgroundDataUsage) {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.CHANGE_BACKGROUND_DATA_SETTING,
+                "ConnectivityService");
+        
+        if (getBackgroundDataSetting() == allowBackgroundDataUsage) return;
+
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Secure.BACKGROUND_DATA, allowBackgroundDataUsage ? 1 : 0);
+        
+        Intent broadcast = new Intent(
+                ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
+        mContext.sendBroadcast(broadcast);
+    }    
+    
+    private int getNumConnectedNetworks() {
+        int numConnectedNets = 0;
+
+        for (NetworkStateTracker nt : mNetTrackers) {
+            if (nt.getNetworkInfo().isConnected() && !nt.isTeardownRequested()) {
+                ++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());
+
+        mNetTrackers[info.getType()].setTeardownRequested(false);
+        /*
+         * 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.
+         */
+        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;
+        }
+
+        /**
+         * See if the other network is available to fail over to.
+         * If is not available, we enable it anyway, so that it
+         * will be able to connect when it does become available,
+         * but we report a total loss of connectivity rather than
+         * report that we are attempting to fail over.
+         */
+        NetworkInfo switchTo = null;
+        if (newNet.isAvailable()) {
+            mActiveNetwork = newNet;
+            switchTo = newNet.getNetworkInfo();
+            switchTo.setFailover(true);
+            if (!switchTo.isConnectedOrConnecting()) {
+                newNet.reconnect();
+            }
+        } else {
+            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);
+    }
+
+    /**
+     * Called when an attempt to fail over to another network has failed.
+     * @param info the {@link NetworkInfo} for the failed network
+     */
+    private void handleConnectionFailure(NetworkInfo info) {
+        mNetTrackers[info.getType()].setTeardownRequested(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 connected to a non-preferred
+         * network that now needs to be torn down.
+         */
+        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;
+        thisNet.setTeardownRequested(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");
+            }
+        }
+
+        /*
+         * Note that if toredown is true, deadnet cannot be null, so there is
+         * no danger of a null pointer exception here..
+         */
+        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 netType = ConnectivityManager.TYPE_WIFI; netType != stopValue; netType += incrValue) {
+            NetworkStateTracker nt = mNetTrackers[netType];
+            if (nt.getNetworkInfo().isConnected() && !nt.isTeardownRequested()) {
+                ++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(sDnsChangeCounter++));
+        return numConnectedNets;
+    }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mContext.checkCallingOrSelfPermission(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-13] Reserved for future use
+                    // [12-9] Network subtype (for mobile network, as defined by 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) |
+                            (info.getSubtype() << 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;
+
+                case NetworkStateTracker.EVENT_ROAMING_CHANGED:
+                    // fill me in
+                    break;
+
+                case NetworkStateTracker.EVENT_NETWORK_SUBTYPE_CHANGED:
+                    // fill me in
+                    break;
+            }
+        }
+    }
+}
