ConnectivityService.java revision b06324a5c1af11b0fef76bdafa569a60498a93d2
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.Notification;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.NotificationManager;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.ConnectivityManager;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.IConnectivityManager;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.MobileDataStateTracker;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.NetworkInfo;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.NetworkStateTracker;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.wifi.WifiStateTracker;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
3342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwaltimport android.os.IBinder;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Looper;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
3642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwaltimport android.os.RemoteException;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemProperties;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings;
4042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwaltimport android.text.TextUtils;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.EventLog;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwaltimport com.android.internal.telephony.Phone;
4542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter;
4842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwaltimport java.util.ArrayList;
4942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwaltimport java.util.List;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class ConnectivityService extends IConnectivityManager.Stub {
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private static final boolean DBG = true;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "ConnectivityService";
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Event log tags (must be in sync with event-log-tags)
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int EVENTLOG_CONNECTIVITY_STATE_CHANGED = 50020;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    // how long to wait before switching back to a radio's default network
6342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
6442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    // system property that can override the above value
6542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
6642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            "android.telephony.apn-restore";
6742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sometimes we want to refer to the individual network state
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * trackers separately, and sometimes we just want to treat them
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * abstractly.
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private NetworkStateTracker mNetTrackers[];
7442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
7542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    /**
7642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt     * A per Net list of the PID's that requested access to the net
7742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt     * used both as a refcount and for per-PID DNS selection
7842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt     */
7942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private List mNetRequestersPids[];
8042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private WifiWatchdogService mWifiWatchdogService;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    // priority order of the nettrackers
8442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    // (excluding dynamically set mNetworkPreference)
8542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    // TODO - move mNetworkTypePreference into this
8642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private int[] mPriorityList;
8742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Context mContext;
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mNetworkPreference;
9042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private int mActiveDefaultNetwork = -1;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mNumDnsEntries;
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mTestMode;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static ConnectivityService sServiceInstance;
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private Handler mHandler;
9842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
9942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    // list of DeathRecipients used to make sure features are turned off when
10042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    // a process dies
10142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private List mFeatureUsers;
10242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
1030f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood    private boolean mSystemReady;
1040f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood    private ArrayList<Intent> mDeferredBroadcasts;
1050f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood
10642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private class NetworkAttributes {
10742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        /**
10842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt         * Class for holding settings read from resources.
10942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt         */
11042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public String mName;
11142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public int mType;
11242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public int mRadio;
11342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public int mPriority;
11442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public NetworkAttributes(String init) {
11542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            String fragments[] = init.split(",");
11642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mName = fragments[0].toLowerCase();
11742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (fragments[1].toLowerCase().equals("wifi")) {
11842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                mRadio = ConnectivityManager.TYPE_WIFI;
11942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else {
12042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                mRadio = ConnectivityManager.TYPE_MOBILE;
12142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
12242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (mName.equals("default")) {
12342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                mType = mRadio;
12442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else if (mName.equals("mms")) {
12542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                mType = ConnectivityManager.TYPE_MOBILE_MMS;
12642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else if (mName.equals("supl")) {
12742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                mType = ConnectivityManager.TYPE_MOBILE_SUPL;
12842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else if (mName.equals("dun")) {
12942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                mType = ConnectivityManager.TYPE_MOBILE_DUN;
13042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else if (mName.equals("hipri")) {
13142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                mType = ConnectivityManager.TYPE_MOBILE_HIPRI;
13242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
13342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mPriority = Integer.parseInt(fragments[2]);
13442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
13542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public boolean isDefault() {
13642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            return (mType == mRadio);
13742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
13842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    }
13942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    NetworkAttributes[] mNetAttributes;
14042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
14142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private class RadioAttributes {
14242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public String mName;
14342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public int mPriority;
14442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public int mSimultaneity;
14542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public int mType;
14642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public RadioAttributes(String init) {
14742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            String fragments[] = init.split(",");
14842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mName = fragments[0].toLowerCase();
14942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mPriority = Integer.parseInt(fragments[1]);
15042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mSimultaneity = Integer.parseInt(fragments[2]);
15142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (mName.equals("wifi")) {
15242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                mType = ConnectivityManager.TYPE_WIFI;
15342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else {
15442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                mType = ConnectivityManager.TYPE_MOBILE;
15542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
15642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
15742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    }
15842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    RadioAttributes[] mRadioAttributes;
15942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static class ConnectivityThread extends Thread {
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private Context mContext;
16286e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private ConnectivityThread(Context context) {
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super("ConnectivityThread");
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext = context;
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Looper.prepare();
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sServiceInstance = new ConnectivityService(mContext);
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                notifyAll();
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Looper.loop();
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17786e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public static ConnectivityService getServiceInstance(Context context) {
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ConnectivityThread thread = new ConnectivityThread(context);
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            thread.start();
18186e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (thread) {
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                while (sServiceInstance == null) {
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Wait until sServiceInstance has been initialized.
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        thread.wait();
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (InterruptedException ignore) {
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Log.e(TAG,
18986e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                            "Unexpected InterruptedException while waiting"+
19086e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                            " for ConnectivityService thread");
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19486e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return sServiceInstance;
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19886e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static ConnectivityService getInstance(Context context) {
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ConnectivityThread.getServiceInstance(context);
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20286e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ConnectivityService(Context context) {
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DBG) Log.v(TAG, "ConnectivityService starting up");
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
20642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        mNetTrackers = new NetworkStateTracker[
20742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                ConnectivityManager.MAX_NETWORK_TYPE+1];
20842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        mHandler = new MyHandler();
20986e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNetworkPreference = getPersistedNetworkPreference();
21186e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
21242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        // Load device network attributes from resources
21342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        mNetAttributes = new NetworkAttributes[
21442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                ConnectivityManager.MAX_NETWORK_TYPE+1];
21542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        mRadioAttributes = new RadioAttributes[
21642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                ConnectivityManager.MAX_RADIO_TYPE+1];
21742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        String[] naStrings = context.getResources().getStringArray(
21842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                com.android.internal.R.array.networkAttributes);
21942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        // TODO - what if the setting has gaps/unknown types?
22042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        for (String a : naStrings) {
22142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            NetworkAttributes n = new NetworkAttributes(a);
22242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mNetAttributes[n.mType] = n;
22342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
22442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        String[] raStrings = context.getResources().getStringArray(
22542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                com.android.internal.R.array.radioAttributes);
22642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        for (String a : raStrings) {
22742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            RadioAttributes r = new RadioAttributes(a);
22842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mRadioAttributes[r.mType] = r;
22942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
23042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
23142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        // high priority first
23242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        mPriorityList = new int[naStrings.length];
23342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        {
23442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            int priority = 0; //lowest
23542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            int nextPos = naStrings.length-1;
23642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            while (nextPos>-1) {
23742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                for (int i = 0; i < mNetAttributes.length; i++) {
23842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if(mNetAttributes[i].mPriority == priority) {
23942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        mPriorityList[nextPos--] = i;
24042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
24142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
24242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                priority++;
24342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
24442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
24542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
24642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        mNetRequestersPids =
24742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1];
24842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        for (int i=0; i<=ConnectivityManager.MAX_NETWORK_TYPE; i++) {
24942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mNetRequestersPids[i] = new ArrayList();
25042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
25142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
25242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        mFeatureUsers = new ArrayList();
25342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Create the network state trackers for Wi-Fi and mobile
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * data. Maybe this could be done with a factory class,
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * but it's not clear that it's worth it, given that
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the number of different network types is not going
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * to change very often.
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DBG) Log.v(TAG, "Starting Wifi Service.");
26242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        WifiStateTracker wst = new WifiStateTracker(context, mHandler);
26342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        WifiService wifiService = new WifiService(context, wst);
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ServiceManager.addService(Context.WIFI_SERVICE, wifiService);
26542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;
26642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
26742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        mNetTrackers[ConnectivityManager.TYPE_MOBILE] =
26842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                new MobileDataStateTracker(context, mHandler,
26942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                ConnectivityManager.TYPE_MOBILE, Phone.APN_TYPE_DEFAULT,
27042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                "MOBILE");
27142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
27242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        mNetTrackers[ConnectivityManager.TYPE_MOBILE_MMS] =
27342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                new MobileDataStateTracker(context, mHandler,
27442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                ConnectivityManager.TYPE_MOBILE_MMS, Phone.APN_TYPE_MMS,
27542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                "MOBILE_MMS");
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
27742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        mNetTrackers[ConnectivityManager.TYPE_MOBILE_SUPL] =
27842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                new MobileDataStateTracker(context, mHandler,
27942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                ConnectivityManager.TYPE_MOBILE_SUPL, Phone.APN_TYPE_SUPL,
28042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                "MOBILE_SUPL");
28142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
28242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        mNetTrackers[ConnectivityManager.TYPE_MOBILE_DUN] =
28342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                new MobileDataStateTracker(context, mHandler,
28442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                ConnectivityManager.TYPE_MOBILE_DUN, Phone.APN_TYPE_DUN,
28542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                "MOBILE_DUN");
28642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
28742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI] =
28842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                new MobileDataStateTracker(context, mHandler,
28942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                ConnectivityManager.TYPE_MOBILE_HIPRI, Phone.APN_TYPE_HIPRI,
29042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                "MOBILE_HIPRI");
29186e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNumDnsEntries = 0;
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mTestMode = SystemProperties.get("cm.test.mode").equals("true")
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && SystemProperties.get("ro.build.type").equals("eng");
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (NetworkStateTracker t : mNetTrackers)
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            t.startMonitoring();
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Constructing this starts it too
30142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        mWifiWatchdogService = new WifiWatchdogService(context, wst);
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
30586e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * Sets the preferred network.
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param preference the new preference
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized void setNetworkPreference(int preference) {
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        enforceChangePermission();
31042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (ConnectivityManager.isNetworkTypeValid(preference) &&
31142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                mNetAttributes[preference].isDefault()) {
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mNetworkPreference != preference) {
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                persistNetworkPreference(preference);
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mNetworkPreference = preference;
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                enforcePreference();
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getNetworkPreference() {
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        enforceAccessPermission();
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mNetworkPreference;
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void persistNetworkPreference(int networkPreference) {
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ContentResolver cr = mContext.getContentResolver();
32786e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt        Settings.Secure.putInt(cr, Settings.Secure.NETWORK_PREFERENCE,
32886e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                networkPreference);
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
33086e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getPersistedNetworkPreference() {
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ContentResolver cr = mContext.getContentResolver();
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int networkPrefSetting = Settings.Secure
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                .getInt(cr, Settings.Secure.NETWORK_PREFERENCE, -1);
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (networkPrefSetting != -1) {
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return networkPrefSetting;
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ConnectivityManager.DEFAULT_NETWORK_PREFERENCE;
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
34286e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
34486e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * Make the state of network connectivity conform to the preference settings
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * In this method, we only tear down a non-preferred network. Establishing
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a connection to the preferred network is taken care of when we handle
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the disconnect event from the non-preferred network
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * (see {@link #handleDisconnect(NetworkInfo)}).
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void enforcePreference() {
35142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (mNetTrackers[mNetworkPreference].getNetworkInfo().isConnected())
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
35442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (!mNetTrackers[mNetworkPreference].isAvailable())
35542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            return;
35642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
35742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        for (int t=0; t <= ConnectivityManager.MAX_RADIO_TYPE; t++) {
35842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (t != mNetworkPreference &&
35942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    mNetTrackers[t].getNetworkInfo().isConnected()) {
360ec9fe4672a46eb928ab710d8e3caf2ce046100d4Robert Greenwalt                if (DBG) {
361ec9fe4672a46eb928ab710d8e3caf2ce046100d4Robert Greenwalt                    Log.d(TAG, "tearing down " +
362ec9fe4672a46eb928ab710d8e3caf2ce046100d4Robert Greenwalt                            mNetTrackers[t].getNetworkInfo() +
363ec9fe4672a46eb928ab710d8e3caf2ce046100d4Robert Greenwalt                            " in enforcePreference");
364ec9fe4672a46eb928ab710d8e3caf2ce046100d4Robert Greenwalt                }
36542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                teardown(mNetTrackers[t]);
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean teardown(NetworkStateTracker netTracker) {
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (netTracker.teardown()) {
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            netTracker.setTeardownRequested(true);
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return NetworkInfo for the active (i.e., connected) network interface.
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * It is assumed that at most one network is active at a time. If more
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * than one is active, it is indeterminate which will be returned.
38386e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * @return the info for the active network, or {@code null} if none is
38486e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * active
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public NetworkInfo getActiveNetworkInfo() {
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        enforceAccessPermission();
38842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        for (int type=0; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
38942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (!mNetAttributes[type].isDefault()) {
39042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                continue;
39142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
39242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            NetworkStateTracker t = mNetTrackers[type];
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            NetworkInfo info = t.getNetworkInfo();
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (info.isConnected()) {
39542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (DBG && type != mActiveDefaultNetwork) Log.e(TAG,
39642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        "connected default network is not " +
39742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        "mActiveDefaultNetwork!");
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return info;
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public NetworkInfo getNetworkInfo(int networkType) {
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        enforceAccessPermission();
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ConnectivityManager.isNetworkTypeValid(networkType)) {
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            NetworkStateTracker t = mNetTrackers[networkType];
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (t != null)
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return t.getNetworkInfo();
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public NetworkInfo[] getAllNetworkInfo() {
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        enforceAccessPermission();
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NetworkInfo[] result = new NetworkInfo[mNetTrackers.length];
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int i = 0;
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (NetworkStateTracker t : mNetTrackers) {
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            result[i++] = t.getNetworkInfo();
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean setRadios(boolean turnOn) {
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean result = true;
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        enforceChangePermission();
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (NetworkStateTracker t : mNetTrackers) {
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            result = t.setRadio(turnOn) && result;
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean setRadio(int netType, boolean turnOn) {
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        enforceChangePermission();
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!ConnectivityManager.isNetworkTypeValid(netType)) {
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NetworkStateTracker tracker = mNetTrackers[netType];
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return tracker != null && tracker.setRadio(turnOn);
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
44242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private class FeatureUser implements IBinder.DeathRecipient {
44342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        int mNetworkType;
44442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        String mFeature;
44542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        IBinder mBinder;
44642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        int mPid;
44742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        int mUid;
44842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
44942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        FeatureUser(int type, String feature, IBinder binder) {
45042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            super();
45142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mNetworkType = type;
45242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mFeature = feature;
45342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mBinder = binder;
45442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mPid = getCallingPid();
45542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mUid = getCallingUid();
45642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            try {
45742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                mBinder.linkToDeath(this, 0);
45842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } catch (RemoteException e) {
45942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                binderDied();
46042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
46142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
46242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
46342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        void unlinkDeathRecipient() {
46442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mBinder.unlinkToDeath(this, 0);
46542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
46642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
46742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public void binderDied() {
46842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            Log.d(TAG, "ConnectivityService FeatureUser binderDied(" +
46942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    mNetworkType + ", " + mFeature + ", " + mBinder);
47042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            stopUsingNetworkFeature(mNetworkType, mFeature, mPid, mUid);
47142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
47242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
47342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    }
47442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
47542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    public int startUsingNetworkFeature(int networkType, String feature,
47642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            IBinder binder) {
47742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (DBG) {
47842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            Log.d(TAG, "startUsingNetworkFeature for net " + networkType +
47942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    ": " + feature);
48042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        enforceChangePermission();
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
48342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            return Phone.APN_REQUEST_FAILED;
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
48542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
48642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        synchronized (mFeatureUsers) {
48742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mFeatureUsers.add(new FeatureUser(networkType, feature, binder));
48842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
48942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
49042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        // TODO - move this into the MobileDataStateTracker
49142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        int usedNetworkType = networkType;
49242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if(networkType == ConnectivityManager.TYPE_MOBILE) {
49342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
49442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
49542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
49642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
49742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN)) {
49842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
49942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
50042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
50142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
50242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
50342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        NetworkStateTracker network = mNetTrackers[usedNetworkType];
50442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (network != null) {
50542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (usedNetworkType != networkType) {
50642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                Integer currentPid = new Integer(getCallingPid());
50742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
50842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                NetworkStateTracker radio = mNetTrackers[networkType];
50942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                NetworkInfo ni = network.getNetworkInfo();
51042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
51142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (ni.isAvailable() == false) {
51242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if (DBG) Log.d(TAG, "special network not available");
51342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    return Phone.APN_TYPE_NOT_AVAILABLE;
51442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
51542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
51642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
51742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    // this gets used for per-pid dns when connected
51842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    mNetRequestersPids[usedNetworkType].add(currentPid);
51942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
52042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
521a64bf834ffa677405af1c87c9f53eed0cd3853ceRobert Greenwalt                if ((ni.isConnectedOrConnecting() == true) &&
522a64bf834ffa677405af1c87c9f53eed0cd3853ceRobert Greenwalt                        !network.isTeardownRequested()) {
52342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if (ni.isConnected() == true) {
52442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        // add the pid-specific dns
52542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        handleDnsConfigurationChange();
52642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        if (DBG) Log.d(TAG, "special network already active");
52742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        return Phone.APN_ALREADY_ACTIVE;
52842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
52942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if (DBG) Log.d(TAG, "special network already connecting");
53042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    return Phone.APN_REQUEST_STARTED;
53142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
53242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
53342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                // check if the radio in play can make another contact
53442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                // assume if cannot for now
53542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
53642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                // since we have to drop the default on this radio, setup
53742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                // an automatic event to switch back
53842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if(mHandler.hasMessages(NetworkStateTracker.
53942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        EVENT_RESTORE_DEFAULT_NETWORK, radio) ||
54042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        radio.getNetworkInfo().isConnectedOrConnecting()) {
54142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    mHandler.removeMessages(NetworkStateTracker.
54242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            EVENT_RESTORE_DEFAULT_NETWORK,
54342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            radio);
54442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    mHandler.sendMessageDelayed(mHandler.obtainMessage(
54542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            NetworkStateTracker.EVENT_RESTORE_DEFAULT_NETWORK,
54642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            radio), getRestoreDefaultNetworkDelay());
54742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
54842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (DBG) Log.d(TAG, "reconnecting to special network");
54942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                network.reconnect();
55042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                return Phone.APN_REQUEST_STARTED;
55142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else {
55242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                return network.startUsingNetworkFeature(feature,
55342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        getCallingPid(), getCallingUid());
55442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
55642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        return Phone.APN_TYPE_NOT_AVAILABLE;
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int stopUsingNetworkFeature(int networkType, String feature) {
56042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        return stopUsingNetworkFeature(networkType, feature, getCallingPid(),
56142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                getCallingUid());
56242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    }
56342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
56442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private int stopUsingNetworkFeature(int networkType, String feature,
56542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            int pid, int uid) {
56642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (DBG) {
56742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            Log.d(TAG, "stopUsingNetworkFeature for net " + networkType +
56842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    ": " + feature);
56942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        enforceChangePermission();
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
57442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
57542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        synchronized (mFeatureUsers) {
57642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            for (int i=0; i < mFeatureUsers.size(); i++) {
57742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                FeatureUser u = (FeatureUser)mFeatureUsers.get(i);
57842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (uid == u.mUid && pid == u.mPid &&
57942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        networkType == u.mNetworkType &&
58042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        TextUtils.equals(feature, u.mFeature)) {
58142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    u.unlinkDeathRecipient();
58242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    mFeatureUsers.remove(i);
58342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    break;
58442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
58542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
58642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
58742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
58842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        // TODO - move to MobileDataStateTracker
58942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        int usedNetworkType = networkType;
59042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (networkType == ConnectivityManager.TYPE_MOBILE) {
59142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
59242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
59342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
59442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
59542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN)) {
59642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
59742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
59842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
59942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
60042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
60142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        NetworkStateTracker tracker =  mNetTrackers[usedNetworkType];
60242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if(usedNetworkType != networkType) {
60342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            Integer currentPid = new Integer(pid);
60442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (mNetRequestersPids[usedNetworkType].remove(currentPid)) {
60542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                reassessPidDns(pid, true);
60642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
60742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (mNetRequestersPids[usedNetworkType].size() != 0) {
60842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (DBG) Log.d(TAG, "not tearing down special network - " +
60942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        "others still using it");
61042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                return 1;
61142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
61242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
61342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            tracker.teardown();
61442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            NetworkStateTracker radio = mNetTrackers[networkType];
61542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            // Check if we want to revert to the default
61642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (mHandler.hasMessages(NetworkStateTracker.
61742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    EVENT_RESTORE_DEFAULT_NETWORK, radio)) {
61842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                mHandler.removeMessages(NetworkStateTracker.
61942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        EVENT_RESTORE_DEFAULT_NETWORK, radio);
62042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                radio.reconnect();
62142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
62242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            return 1;
62342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        } else {
62442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            return tracker.stopUsingNetworkFeature(feature, pid, uid);
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Ensure that a network route exists to deliver traffic to the specified
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * host via the specified network interface.
63186e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * @param networkType the type of the network over which traffic to the
63286e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * specified host is to be routed
63386e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * @param hostAddress the IP address of the host to which the route is
63486e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * desired
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return {@code true} on success, {@code false} on failure
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requestRouteToHost(int networkType, int hostAddress) {
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        enforceChangePermission();
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NetworkStateTracker tracker = mNetTrackers[networkType];
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * If there's only one connected network, and it's the one requested,
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * then we don't have to do anything - the requested route already
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * exists. If it's not the requested network, then it's not possible
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * to establish the requested route. Finally, if there is more than
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * one connected network, then we must insert an entry in the routing
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * table.
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (getNumConnectedNetworks() > 1) {
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return tracker.requestRouteToHost(hostAddress);
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
65442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            return (mNetAttributes[networkType].isDefault() &&
65542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    tracker.getNetworkInfo().isConnected());
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see ConnectivityManager#getBackgroundDataSetting()
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean getBackgroundDataSetting() {
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Settings.Secure.getInt(mContext.getContentResolver(),
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Settings.Secure.BACKGROUND_DATA, 1) == 1;
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
66686e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see ConnectivityManager#setBackgroundDataSetting(boolean)
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setBackgroundDataSetting(boolean allowBackgroundDataUsage) {
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                android.Manifest.permission.CHANGE_BACKGROUND_DATA_SETTING,
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                "ConnectivityService");
67486e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (getBackgroundDataSetting() == allowBackgroundDataUsage) return;
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Settings.Secure.putInt(mContext.getContentResolver(),
67886e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                Settings.Secure.BACKGROUND_DATA,
67986e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                allowBackgroundDataUsage ? 1 : 0);
68086e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Intent broadcast = new Intent(
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.sendBroadcast(broadcast);
68486e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt    }
68586e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getNumConnectedNetworks() {
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int numConnectedNets = 0;
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (NetworkStateTracker nt : mNetTrackers) {
69086e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt            if (nt.getNetworkInfo().isConnected() &&
69186e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    !nt.isTeardownRequested()) {
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ++numConnectedNets;
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
695a64bf834ffa677405af1c87c9f53eed0cd3853ceRobert Greenwalt        if (DBG) Log.d(TAG, "numConnectedNets returning "+numConnectedNets);
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return numConnectedNets;
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void enforceAccessPermission() {
70086e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt        mContext.enforceCallingOrSelfPermission(
70186e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                android.Manifest.permission.ACCESS_NETWORK_STATE,
70286e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                "ConnectivityService");
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void enforceChangePermission() {
70686e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt        mContext.enforceCallingOrSelfPermission(
70786e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                android.Manifest.permission.CHANGE_NETWORK_STATE,
70886e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                "ConnectivityService");
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
71286e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * Handle a {@code DISCONNECTED} event. If this pertains to the non-active
71386e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * network, we ignore it. If it is for the active network, we send out a
71486e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * broadcast. But first, we check whether it might be possible to connect
71586e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * to a different network.
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param info the {@code NetworkInfo} for the network
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void handleDisconnect(NetworkInfo info) {
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DBG) Log.v(TAG, "Handle DISCONNECT for " + info.getTypeName());
72142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        int prevNetType = info.getType();
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
72342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        mNetTrackers[prevNetType].setTeardownRequested(false);
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * If the disconnected network is not the active one, then don't report
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * this as a loss of connectivity. What probably happened is that we're
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * getting the disconnect for a network that we explicitly disabled
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * in accordance with network preference policies.
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
73042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (!mNetAttributes[prevNetType].isDefault()) {
73142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            List pids = mNetRequestersPids[prevNetType];
73242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            for (int i = 0; i<pids.size(); i++) {
73342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                Integer pid = (Integer)pids.get(i);
73442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                // will remove them because the net's no longer connected
73542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                // need to do this now as only now do we know the pids and
73642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                // can properly null things that are no longer referenced.
73742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                reassessPidDns(pid.intValue(), false);
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info.isFailover()) {
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            info.setFailover(false);
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info.getReason() != null) {
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info.getExtraInfo() != null) {
75186e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt            intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
75286e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    info.getExtraInfo());
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
75442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
75542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        /*
75642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt         * If this is a default network, check if other defaults are available
75742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt         * or active
75842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt         */
75942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        NetworkStateTracker newNet = null;
76042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (mNetAttributes[prevNetType].isDefault()) {
76142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (DBG) Log.d(TAG, "disconnecting a default network");
76242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (mActiveDefaultNetwork == prevNetType) {
76342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                mActiveDefaultNetwork = -1;
76442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
76542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
76642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            int newType = -1;
76742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            int newPriority = -1;
76842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            for (int checkType=0; checkType <=
76942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
77042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (checkType == prevNetType) {
77142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    continue;
77242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
77342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (mNetAttributes[checkType].isDefault()) {
77442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    /* TODO - if we have multiple nets we could use
77542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                     * we may want to put more thought into which we choose
77642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                     */
77742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if (checkType == mNetworkPreference) {
77842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        newType = checkType;
77942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        break;
78042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
78142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if (mRadioAttributes[mNetAttributes[checkType].mRadio].
78242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            mPriority > newPriority) {
78342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        newType = checkType;
78442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        newPriority = mRadioAttributes[mNetAttributes[newType].
78542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                                mRadio].mPriority;
78642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
78742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
78842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
78942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
79042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (newType != -1) {
79142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                newNet = mNetTrackers[newType];
79242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                /**
79342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                 * See if the other network is available to fail over to.
79442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                 * If is not available, we enable it anyway, so that it
79542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                 * will be able to connect when it does become available,
79642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                 * but we report a total loss of connectivity rather than
79742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                 * report that we are attempting to fail over.
79842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                 */
79942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (newNet.isAvailable()) {
80042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    NetworkInfo switchTo = newNet.getNetworkInfo();
80142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    switchTo.setFailover(true);
802a64bf834ffa677405af1c87c9f53eed0cd3853ceRobert Greenwalt                    if (!switchTo.isConnectedOrConnecting() ||
803a64bf834ffa677405af1c87c9f53eed0cd3853ceRobert Greenwalt                            newNet.isTeardownRequested()) {
80442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        newNet.reconnect();
80542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
80642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if (DBG) {
80742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        if (switchTo.isConnected()) {
80842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            Log.v(TAG, "Switching to already connected " +
80942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                                    switchTo.getTypeName());
81042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        } else {
81142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            Log.v(TAG, "Attempting to switch to " +
81242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                                    switchTo.getTypeName());
81342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        }
81442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
81542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    intent.putExtra(ConnectivityManager.
81642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            EXTRA_OTHER_NETWORK_INFO, switchTo);
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
81842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    newNet.reconnect();
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
82042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else {
82142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,
82242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        true);
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
82542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
82642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        // do this before we broadcast the change
82742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        handleConnectivityChange();
82842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
82986e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt        if (DBG) Log.v(TAG, "Sending DISCONNECT bcast for " +
83086e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                info.getTypeName() +
83142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                (newNet == null || !newNet.isAvailable() ? "" : " other=" +
83242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                newNet.getNetworkInfo().getTypeName()));
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8340f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood        sendStickyBroadcast(intent);
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
83686e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt         * If the failover network is already connected, then immediately send
83786e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt         * out a followup broadcast indicating successful failover
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
83942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (newNet != null && newNet.getNetworkInfo().isConnected())
84042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            sendConnectedBroadcast(newNet.getNetworkInfo());
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void sendConnectedBroadcast(NetworkInfo info) {
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info.isFailover()) {
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            info.setFailover(false);
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info.getReason() != null) {
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info.getExtraInfo() != null) {
85486e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt            intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
85586e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    info.getExtraInfo());
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8570f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood        sendStickyBroadcast(intent);
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when an attempt to fail over to another network has failed.
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param info the {@link NetworkInfo} for the failed network
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void handleConnectionFailure(NetworkInfo info) {
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNetTrackers[info.getType()].setTeardownRequested(false);
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
86742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        String reason = info.getReason();
86842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        String extraInfo = info.getExtraInfo();
86942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
87042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (DBG) {
87142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            String reasonText;
87242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (reason == null) {
87342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                reasonText = ".";
87442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else {
87542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                reasonText = " (" + reason + ").";
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
87742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            Log.v(TAG, "Attempt to connect to " + info.getTypeName() +
87842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    " failed" + reasonText);
87942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
88086e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
88142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
88242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
88342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (getActiveNetworkInfo() == null) {
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
88642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (reason != null) {
88742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            intent.putExtra(ConnectivityManager.EXTRA_REASON, reason);
88842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
88942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (extraInfo != null) {
89042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, extraInfo);
89142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
89242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (info.isFailover()) {
89342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
89442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            info.setFailover(false);
89542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
8960f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood        sendStickyBroadcast(intent);
8970f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood    }
8980f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood
8990f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood    private void sendStickyBroadcast(Intent intent) {
9000f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood        synchronized(this) {
9010f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood            if (mSystemReady) {
9020f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood                mContext.sendStickyBroadcast(intent);
9030f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood            } else {
9040f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood                if (mDeferredBroadcasts == null) {
9050f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood                    mDeferredBroadcasts = new ArrayList<Intent>();
9060f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood                }
9070f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood                mDeferredBroadcasts.add(intent);
9080f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood            }
9090f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood        }
9100f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood    }
9110f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood
9120f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood    void systemReady() {
9130f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood        synchronized(this) {
9140f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood            mSystemReady = true;
9150f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood            if (mDeferredBroadcasts != null) {
9160f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood                int count = mDeferredBroadcasts.size();
9170f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood                for (int i = 0; i < count; i++) {
9180f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood                    mContext.sendStickyBroadcast(mDeferredBroadcasts.get(i));
9190f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood                }
9200f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood                mDeferredBroadcasts = null;
9210f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood            }
9220f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood        }
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void handleConnect(NetworkInfo info) {
92642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (DBG) Log.d(TAG, "Handle CONNECT for " + info.getTypeName());
92742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
92842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        int type = info.getType();
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // snapshot isFailover, because sendConnectedBroadcast() resets it
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean isFailover = info.isFailover();
93242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        NetworkStateTracker thisNet = mNetTrackers[type];
93342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
93442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        // if this is a default net and other default is running
93542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        // kill the one not preferred
93642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (mNetAttributes[type].isDefault()) {
93742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (DBG) Log.d(TAG, "connecting to a default network");
93842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
93942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if ((type != mNetworkPreference &&
94042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        mNetAttributes[mActiveDefaultNetwork].mPriority >
94142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        mNetAttributes[type].mPriority) ||
94242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        mNetworkPreference == mActiveDefaultNetwork) {
94342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        // don't accept this one
94442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        if (DBG) Log.v(TAG, "Not broadcasting CONNECT_ACTION " +
94542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                                "to torn down network " + info.getTypeName());
94642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        teardown(thisNet);
94742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        return;
94842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                } else {
94942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    // tear down the other
95042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    NetworkStateTracker otherNet =
95142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            mNetTrackers[mActiveDefaultNetwork];
95242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if (DBG) Log.v(TAG, "Policy requires " +
95342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            otherNet.getNetworkInfo().getTypeName() +
95442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            " teardown");
95542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if (!teardown(otherNet)) {
95642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        Log.e(TAG, "Network declined teardown request");
95742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        return;
95842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
95942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if (isFailover) {
96042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        otherNet.releaseWakeLock();
96142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
96242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
96442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mActiveDefaultNetwork = type;
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
96642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        thisNet.setTeardownRequested(false);
96742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (DBG) Log.d(TAG, "Sending CONNECT bcast for " + info.getTypeName());
96842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        thisNet.updateNetworkSettings();
96942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        handleConnectivityChange();
97042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        sendConnectedBroadcast(info);
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void handleScanResultsAvailable(NetworkInfo info) {
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int networkType = info.getType();
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (networkType != ConnectivityManager.TYPE_WIFI) {
97686e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt            if (DBG) Log.v(TAG, "Got ScanResultsAvailable for " +
97786e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    info.getTypeName() + " network. Don't know how to handle.");
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
97986e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNetTrackers[networkType].interpretScanResultsAvailable();
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
98386e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt    private void handleNotificationChange(boolean visible, int id,
98486e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt            Notification notification) {
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NotificationManager notificationManager = (NotificationManager) mContext
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                .getSystemService(Context.NOTIFICATION_SERVICE);
98786e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (visible) {
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notificationManager.notify(id, notification);
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notificationManager.cancel(id);
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * After any kind of change in the connectivity state of any network,
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * make sure that anything that depends on the connectivity state of
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * more than one network is set up correctly. We're mainly concerned
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * with making sure that the list of DNS servers is set up  according
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to which networks are connected, and ensuring that the right routing
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * table entries exist.
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void handleConnectivityChange() {
100442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (DBG) Log.d(TAG, "handleConnectivityChange");
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
100642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt         * If a non-default network is enabled, add the host routes that
100742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt         * will allow it's DNS servers to be accessed.  Only
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * If both mobile and wifi are enabled, add the host routes that
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * will allow MMS traffic to pass on the mobile network. But
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * remove the default route for the mobile network, so that there
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * will be only one default route, to ensure that all traffic
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * except MMS will travel via Wi-Fi.
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
101442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        handleDnsConfigurationChange();
101542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
101642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        for (int netType : mPriorityList) {
101742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
101842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (mNetAttributes[netType].isDefault()) {
101942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    mNetTrackers[netType].addDefaultRoute();
102042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                } else {
102142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    mNetTrackers[netType].addPrivateDnsRoutes();
102242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
102342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else {
102442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (mNetAttributes[netType].isDefault()) {
102542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    mNetTrackers[netType].removeDefaultRoute();
102642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                } else {
102742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    mNetTrackers[netType].removePrivateDnsRoutes();
102842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
102942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
103342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    /**
103442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt     * Adjust the per-process dns entries (net.dns<x>.<pid>) based
103542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt     * on the highest priority active net which this process requested.
103642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt     * If there aren't any, clear it out
103742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt     */
103842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private void reassessPidDns(int myPid, boolean doBump)
103942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    {
104042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (DBG) Log.d(TAG, "reassessPidDns for pid " + myPid);
104142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        for(int i : mPriorityList) {
104242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (mNetAttributes[i].isDefault()) {
104342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                continue;
104442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
104542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            NetworkStateTracker nt = mNetTrackers[i];
104642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (nt.getNetworkInfo().isConnected() &&
104742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    !nt.isTeardownRequested()) {
104842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                List pids = mNetRequestersPids[i];
104942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                for (int j=0; j<pids.size(); j++) {
105042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    Integer pid = (Integer)pids.get(j);
105142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if (pid.intValue() == myPid) {
105242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        String[] dnsList = nt.getNameServers();
105342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        writePidDns(dnsList, myPid);
105442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        if (doBump) {
105542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            bumpDns();
105642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        }
105742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        return;
105842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
105942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
106042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt           }
106142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
106242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        // nothing found - delete
106342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        for (int i = 1; ; i++) {
106442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            String prop = "net.dns" + i + "." + myPid;
106542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (SystemProperties.get(prop).length() == 0) {
106642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (doBump) {
106742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    bumpDns();
106842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
106942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                return;
107042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
107142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            SystemProperties.set(prop, "");
107242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
107342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    }
107442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
107542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private void writePidDns(String[] dnsList, int pid) {
107642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        int j = 1;
107742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        for (String dns : dnsList) {
107842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (dns != null && !TextUtils.equals(dns, "0.0.0.0")) {
107942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                SystemProperties.set("net.dns" + j++ + "." + pid, dns);
108042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
108142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
108242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    }
108342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
108442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private void bumpDns() {
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
108642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt         * Bump the property that tells the name resolver library to reread
108742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt         * the DNS server list from the properties.
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
108942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        String propVal = SystemProperties.get("net.dnschange");
109042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        int n = 0;
109142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (propVal.length() != 0) {
109242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            try {
109342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                n = Integer.parseInt(propVal);
109442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } catch (NumberFormatException e) {}
109542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
109642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        SystemProperties.set("net.dnschange", "" + (n+1));
109742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    }
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
109942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private void handleDnsConfigurationChange() {
110042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (DBG) Log.d(TAG, "handleDnsConfig Change");
110142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        // add default net's dns entries
110242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        for (int x = mPriorityList.length-1; x>= 0; x--) {
110342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            int netType = mPriorityList[x];
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            NetworkStateTracker nt = mNetTrackers[netType];
110542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (DBG) Log.d(TAG, " checking " + nt);
110642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (nt != null && nt.getNetworkInfo().isConnected() &&
110786e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    !nt.isTeardownRequested()) {
110842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (DBG) Log.d(TAG, "  connected");
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String[] dnsList = nt.getNameServers();
111042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (mNetAttributes[netType].isDefault()) {
111142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    int j = 1;
111242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    for (String dns : dnsList) {
111342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        if (dns != null && !TextUtils.equals(dns, "0.0.0.0")) {
1114b06324a5c1af11b0fef76bdafa569a60498a93d2Robert Greenwalt                            if (DBG) Log.d(TAG, "  adding "+dns);
111542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            SystemProperties.set("net.dns" + j++, dns);
111642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        }
111742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
111842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    for (int k=j ; k<mNumDnsEntries; k++) {
1119b06324a5c1af11b0fef76bdafa569a60498a93d2Robert Greenwalt                        if (DBG) Log.d(TAG, "erasing net.dns" + k);
1120b06324a5c1af11b0fef76bdafa569a60498a93d2Robert Greenwalt                        SystemProperties.set("net.dns" + k, "");
112142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
112242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    mNumDnsEntries = j;
112342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                } else {
112442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    // set per-pid dns for attached secondary nets
112542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    List pids = mNetRequestersPids[netType];
112642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    for (int y=0; y< pids.size(); y++) {
112742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        Integer pid = (Integer)pids.get(y);
112842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        writePidDns(dnsList, pid.intValue());
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
113342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
113442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        bumpDns();
113542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    }
113642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
113742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private int getRestoreDefaultNetworkDelay() {
113842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        String restoreDefaultNetworkDelayStr = SystemProperties.get(
113942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                NETWORK_RESTORE_DELAY_PROP_NAME);
114042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if(restoreDefaultNetworkDelayStr != null &&
114142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                restoreDefaultNetworkDelayStr.length() != 0) {
114242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            try {
114342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                return Integer.valueOf(restoreDefaultNetworkDelayStr);
114442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } catch (NumberFormatException e) {
114542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
114742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        return RESTORE_DEFAULT_NETWORK_DELAY;
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
115286e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt        if (mContext.checkCallingOrSelfPermission(
115386e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                android.Manifest.permission.DUMP)
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
115586e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt            pw.println("Permission Denial: can't dump ConnectivityService " +
115686e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    "from from pid=" + Binder.getCallingPid() + ", uid=" +
115786e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    Binder.getCallingUid());
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pw.println();
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (NetworkStateTracker nst : mNetTrackers) {
116242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (nst.getNetworkInfo().isConnected()) {
116342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                pw.println("Active network: " + nst.getNetworkInfo().
116442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        getTypeName());
116542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(nst.getNetworkInfo());
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(nst);
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println();
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
117242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    // must be stateless - things change under us.
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class MyHandler extends Handler {
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void handleMessage(Message msg) {
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            NetworkInfo info;
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (msg.what) {
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case NetworkStateTracker.EVENT_STATE_CHANGED:
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    info = (NetworkInfo) msg.obj;
118042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if (DBG) Log.d(TAG, "ConnectivityChange for " +
118186e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                            info.getTypeName() + ": " +
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            info.getState() + "/" + info.getDetailedState());
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Connectivity state changed:
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // [31-13] Reserved for future use
118686e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    // [12-9] Network subtype (for mobile network, as defined
118786e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    //         by TelephonyManager)
118886e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    // [8-3] Detailed state ordinal (as defined by
118986e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    //         NetworkInfo.DetailedState)
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // [2-0] Network type (as defined by ConnectivityManager)
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    int eventLogParam = (info.getType() & 0x7) |
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            ((info.getDetailedState().ordinal() & 0x3f) << 3) |
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (info.getSubtype() << 9);
119486e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    EventLog.writeEvent(EVENTLOG_CONNECTIVITY_STATE_CHANGED,
119586e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                            eventLogParam);
119686e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
119786e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    if (info.getDetailedState() ==
119886e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                            NetworkInfo.DetailedState.FAILED) {
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        handleConnectionFailure(info);
120086e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    } else if (info.getState() ==
120186e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                            NetworkInfo.State.DISCONNECTED) {
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        handleDisconnect(info);
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else if (info.getState() == NetworkInfo.State.SUSPENDED) {
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // TODO: need to think this over.
120586e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                        // the logic here is, handle SUSPENDED the same as
120686e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                        // DISCONNECTED. The only difference being we are
120786e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                        // broadcasting an intent with NetworkInfo that's
120886e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                        // suspended. This allows the applications an
120986e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                        // opportunity to handle DISCONNECTED and SUSPENDED
121086e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                        // differently, or not.
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        handleDisconnect(info);
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else if (info.getState() == NetworkInfo.State.CONNECTED) {
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        handleConnect(info);
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case NetworkStateTracker.EVENT_SCAN_RESULTS_AVAILABLE:
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    info = (NetworkInfo) msg.obj;
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    handleScanResultsAvailable(info);
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
122186e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case NetworkStateTracker.EVENT_NOTIFICATION_CHANGED:
122386e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    handleNotificationChange(msg.arg1 == 1, msg.arg2,
122486e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                            (Notification) msg.obj);
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
122742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    handleDnsConfigurationChange();
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case NetworkStateTracker.EVENT_ROAMING_CHANGED:
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // fill me in
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case NetworkStateTracker.EVENT_NETWORK_SUBTYPE_CHANGED:
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // fill me in
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
123742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                case NetworkStateTracker.EVENT_RESTORE_DEFAULT_NETWORK:
123842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    for (NetworkStateTracker net : mNetTrackers) {
123942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        NetworkInfo i = net.getNetworkInfo();
124042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        if (i.isConnected() &&
124142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                                !mNetAttributes[i.getType()].isDefault()) {
1242ec9fe4672a46eb928ab710d8e3caf2ce046100d4Robert Greenwalt                            if (DBG) {
1243ec9fe4672a46eb928ab710d8e3caf2ce046100d4Robert Greenwalt                                Log.d(TAG, "tearing down " + i +
1244ec9fe4672a46eb928ab710d8e3caf2ce046100d4Robert Greenwalt                                        " to restore the default network");
1245ec9fe4672a46eb928ab710d8e3caf2ce046100d4Robert Greenwalt                            }
124642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            teardown(net);
124742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        }
124842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
124942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    break;
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1254