ConnectivityService.java revision b928535902b204ac3ec25f161352786842248767
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
56d8df149cfb82cf02cef7e04c05f229d7caf7fe90Robert Greenwalt    private static final boolean DBG = true;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "ConnectivityService";
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    // how long to wait before switching back to a radio's default network
6042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
6142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    // system property that can override the above value
6242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
6342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            "android.telephony.apn-restore";
6442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sometimes we want to refer to the individual network state
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * trackers separately, and sometimes we just want to treat them
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * abstractly.
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private NetworkStateTracker mNetTrackers[];
7142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
7242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    /**
7342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt     * A per Net list of the PID's that requested access to the net
7442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt     * used both as a refcount and for per-PID DNS selection
7542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt     */
7642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private List mNetRequestersPids[];
7742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private WifiWatchdogService mWifiWatchdogService;
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    // priority order of the nettrackers
8142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    // (excluding dynamically set mNetworkPreference)
8242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    // TODO - move mNetworkTypePreference into this
8342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private int[] mPriorityList;
8442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Context mContext;
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mNetworkPreference;
8742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private int mActiveDefaultNetwork = -1;
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mNumDnsEntries;
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mTestMode;
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static ConnectivityService sServiceInstance;
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private Handler mHandler;
9542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
9642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    // list of DeathRecipients used to make sure features are turned off when
9742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    // a process dies
9842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private List mFeatureUsers;
9942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
1000f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood    private boolean mSystemReady;
1011c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn    private Intent mInitialBroadcast;
1020f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood
103511288a04639859a6d9bbfedfa2f2b4d7d2c3e88Robert Greenwalt    private static class NetworkAttributes {
10442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        /**
10542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt         * Class for holding settings read from resources.
10642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt         */
10742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public String mName;
10842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public int mType;
10942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public int mRadio;
11042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public int mPriority;
111511288a04639859a6d9bbfedfa2f2b4d7d2c3e88Robert Greenwalt        public NetworkInfo.State mLastState;
11242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public NetworkAttributes(String init) {
11342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            String fragments[] = init.split(",");
11442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mName = fragments[0].toLowerCase();
1155154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            mType = Integer.parseInt(fragments[1]);
1165154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            mRadio = Integer.parseInt(fragments[2]);
1175154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            mPriority = Integer.parseInt(fragments[3]);
118511288a04639859a6d9bbfedfa2f2b4d7d2c3e88Robert Greenwalt            mLastState = NetworkInfo.State.UNKNOWN;
11942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
12042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public boolean isDefault() {
12142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            return (mType == mRadio);
12242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
12342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    }
12442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    NetworkAttributes[] mNetAttributes;
1255154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt    int mNetworksDefined;
12642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
127511288a04639859a6d9bbfedfa2f2b4d7d2c3e88Robert Greenwalt    private static class RadioAttributes {
12842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public int mSimultaneity;
12942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public int mType;
13042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public RadioAttributes(String init) {
13142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            String fragments[] = init.split(",");
1325154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            mType = Integer.parseInt(fragments[0]);
1335154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            mSimultaneity = Integer.parseInt(fragments[1]);
13442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
13542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    }
13642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    RadioAttributes[] mRadioAttributes;
13742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static class ConnectivityThread extends Thread {
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private Context mContext;
14086e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private ConnectivityThread(Context context) {
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super("ConnectivityThread");
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext = context;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Looper.prepare();
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sServiceInstance = new ConnectivityService(mContext);
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                notifyAll();
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Looper.loop();
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15586e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public static ConnectivityService getServiceInstance(Context context) {
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ConnectivityThread thread = new ConnectivityThread(context);
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            thread.start();
15986e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (thread) {
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                while (sServiceInstance == null) {
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Wait until sServiceInstance has been initialized.
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        thread.wait();
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (InterruptedException ignore) {
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Log.e(TAG,
16786e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                            "Unexpected InterruptedException while waiting"+
16886e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                            " for ConnectivityService thread");
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17286e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return sServiceInstance;
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17686e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static ConnectivityService getInstance(Context context) {
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ConnectivityThread.getServiceInstance(context);
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18086e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ConnectivityService(Context context) {
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DBG) Log.v(TAG, "ConnectivityService starting up");
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
18442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        mNetTrackers = new NetworkStateTracker[
18542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                ConnectivityManager.MAX_NETWORK_TYPE+1];
18642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        mHandler = new MyHandler();
18786e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNetworkPreference = getPersistedNetworkPreference();
18986e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
1905154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt        mRadioAttributes = new RadioAttributes[ConnectivityManager.MAX_RADIO_TYPE+1];
1915154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt        mNetAttributes = new NetworkAttributes[ConnectivityManager.MAX_NETWORK_TYPE+1];
1925154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt
19342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        // Load device network attributes from resources
19442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        String[] raStrings = context.getResources().getStringArray(
19542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                com.android.internal.R.array.radioAttributes);
1965154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt        for (String raString : raStrings) {
1975154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            RadioAttributes r = new RadioAttributes(raString);
1985154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            if (r.mType > ConnectivityManager.MAX_RADIO_TYPE) {
1995154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                Log.e(TAG, "Error in radioAttributes - ignoring attempt to define type " + r.mType);
2005154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                continue;
2015154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            }
2025154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            if (mRadioAttributes[r.mType] != null) {
2035154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                Log.e(TAG, "Error in radioAttributes - ignoring attempt to redefine type " +
2045154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                        r.mType);
2055154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                continue;
2065154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            }
20742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mRadioAttributes[r.mType] = r;
20842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
20942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
2105154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt        String[] naStrings = context.getResources().getStringArray(
2115154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                com.android.internal.R.array.networkAttributes);
2125154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt        for (String naString : naStrings) {
2135154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            try {
2145154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                NetworkAttributes n = new NetworkAttributes(naString);
2155154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                if (n.mType > ConnectivityManager.MAX_NETWORK_TYPE) {
2165154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                    Log.e(TAG, "Error in networkAttributes - ignoring attempt to define type " +
2175154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                            n.mType);
2185154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                    continue;
2195154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                }
2205154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                if (mNetAttributes[n.mType] != null) {
2215154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                    Log.e(TAG, "Error in networkAttributes - ignoring attempt to redefine type " +
2225154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                            n.mType);
2235154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                    continue;
2245154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                }
2255154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                if (mRadioAttributes[n.mRadio] == null) {
2265154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                    Log.e(TAG, "Error in networkAttributes - ignoring attempt to use undefined " +
2275154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                            "radio " + n.mRadio + " in network type " + n.mType);
2285154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                    continue;
2295154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                }
2305154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                mNetAttributes[n.mType] = n;
2315154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                mNetworksDefined++;
2325154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            } catch(Exception e) {
2335154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                // ignore it - leave the entry null
2345154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            }
2355154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt        }
2365154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt
23742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        // high priority first
2385154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt        mPriorityList = new int[mNetworksDefined];
23942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        {
2405154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            int insertionPoint = mNetworksDefined-1;
2415154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            int currentLowest = 0;
2425154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            int nextLowest = 0;
2435154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            while (insertionPoint > -1) {
2445154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                for (NetworkAttributes na : mNetAttributes) {
2455154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                    if (na == null) continue;
2465154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                    if (na.mPriority < currentLowest) continue;
2475154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                    if (na.mPriority > currentLowest) {
2485154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                        if (na.mPriority < nextLowest || nextLowest == 0) {
2495154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                            nextLowest = na.mPriority;
2505154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                        }
2515154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                        continue;
25242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
2535154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                    mPriorityList[insertionPoint--] = na.mType;
25442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
2555154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                currentLowest = nextLowest;
2565154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                nextLowest = 0;
25742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
25842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
25942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
2605154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt        mNetRequestersPids = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1];
2615154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt        for (int i : mPriorityList) {
26242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mNetRequestersPids[i] = new ArrayList();
26342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
26442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
26542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        mFeatureUsers = new ArrayList();
26642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
2675154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt        mNumDnsEntries = 0;
2685154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt
2695154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt        mTestMode = SystemProperties.get("cm.test.mode").equals("true")
2705154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                && SystemProperties.get("ro.build.type").equals("eng");
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Create the network state trackers for Wi-Fi and mobile
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * data. Maybe this could be done with a factory class,
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * but it's not clear that it's worth it, given that
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the number of different network types is not going
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * to change very often.
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2785154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt        for (int netType : mPriorityList) {
2795154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            switch (mNetAttributes[netType].mRadio) {
2805154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            case ConnectivityManager.TYPE_WIFI:
2815154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                if (DBG) Log.v(TAG, "Starting Wifi Service.");
2825154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                WifiStateTracker wst = new WifiStateTracker(context, mHandler);
2835154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                WifiService wifiService = new WifiService(context, wst);
2845154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                ServiceManager.addService(Context.WIFI_SERVICE, wifiService);
2855154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;
2865154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                wst.startMonitoring();
2875154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt
2885154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                // Constructing this starts it too
2895154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                mWifiWatchdogService = new WifiWatchdogService(context, wst);
2905154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                break;
2915154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            case ConnectivityManager.TYPE_MOBILE:
2925154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                mNetTrackers[netType] = new MobileDataStateTracker(context, mHandler,
2935154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                    netType, mNetAttributes[netType].mName);
2945154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                mNetTrackers[netType].startMonitoring();
2955154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                break;
2965154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            default:
2975154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                Log.e(TAG, "Trying to create a DataStateTracker for an unknown radio type " +
2985154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                        mNetAttributes[netType].mRadio);
2995154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                continue;
3005154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            }
3015154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt        }
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3045154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
30686e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * Sets the preferred network.
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param preference the new preference
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized void setNetworkPreference(int preference) {
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        enforceChangePermission();
31142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (ConnectivityManager.isNetworkTypeValid(preference) &&
3125154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                mNetAttributes[preference] != null &&
31342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                mNetAttributes[preference].isDefault()) {
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mNetworkPreference != preference) {
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                persistNetworkPreference(preference);
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mNetworkPreference = preference;
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                enforcePreference();
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getNetworkPreference() {
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        enforceAccessPermission();
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mNetworkPreference;
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void persistNetworkPreference(int networkPreference) {
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ContentResolver cr = mContext.getContentResolver();
32986e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt        Settings.Secure.putInt(cr, Settings.Secure.NETWORK_PREFERENCE,
33086e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                networkPreference);
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
33286e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getPersistedNetworkPreference() {
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ContentResolver cr = mContext.getContentResolver();
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int networkPrefSetting = Settings.Secure
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                .getInt(cr, Settings.Secure.NETWORK_PREFERENCE, -1);
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (networkPrefSetting != -1) {
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return networkPrefSetting;
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ConnectivityManager.DEFAULT_NETWORK_PREFERENCE;
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
34486e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
34686e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * Make the state of network connectivity conform to the preference settings
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * In this method, we only tear down a non-preferred network. Establishing
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a connection to the preferred network is taken care of when we handle
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the disconnect event from the non-preferred network
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * (see {@link #handleDisconnect(NetworkInfo)}).
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void enforcePreference() {
35342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (mNetTrackers[mNetworkPreference].getNetworkInfo().isConnected())
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
35642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (!mNetTrackers[mNetworkPreference].isAvailable())
35742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            return;
35842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
35942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        for (int t=0; t <= ConnectivityManager.MAX_RADIO_TYPE; t++) {
3605154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            if (t != mNetworkPreference && mNetTrackers[t] != null &&
36142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    mNetTrackers[t].getNetworkInfo().isConnected()) {
362ec9fe4672a46eb928ab710d8e3caf2ce046100d4Robert Greenwalt                if (DBG) {
363ec9fe4672a46eb928ab710d8e3caf2ce046100d4Robert Greenwalt                    Log.d(TAG, "tearing down " +
364ec9fe4672a46eb928ab710d8e3caf2ce046100d4Robert Greenwalt                            mNetTrackers[t].getNetworkInfo() +
365ec9fe4672a46eb928ab710d8e3caf2ce046100d4Robert Greenwalt                            " in enforcePreference");
366ec9fe4672a46eb928ab710d8e3caf2ce046100d4Robert Greenwalt                }
36742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                teardown(mNetTrackers[t]);
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean teardown(NetworkStateTracker netTracker) {
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (netTracker.teardown()) {
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            netTracker.setTeardownRequested(true);
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return NetworkInfo for the active (i.e., connected) network interface.
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * It is assumed that at most one network is active at a time. If more
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * than one is active, it is indeterminate which will be returned.
38586e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * @return the info for the active network, or {@code null} if none is
38686e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * active
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public NetworkInfo getActiveNetworkInfo() {
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        enforceAccessPermission();
39042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        for (int type=0; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
3915154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            if (mNetAttributes[type] == null || !mNetAttributes[type].isDefault()) {
39242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                continue;
39342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
39442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            NetworkStateTracker t = mNetTrackers[type];
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            NetworkInfo info = t.getNetworkInfo();
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (info.isConnected()) {
39742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (DBG && type != mActiveDefaultNetwork) Log.e(TAG,
39842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        "connected default network is not " +
39942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        "mActiveDefaultNetwork!");
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return info;
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public NetworkInfo getNetworkInfo(int networkType) {
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        enforceAccessPermission();
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ConnectivityManager.isNetworkTypeValid(networkType)) {
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            NetworkStateTracker t = mNetTrackers[networkType];
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (t != null)
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return t.getNetworkInfo();
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public NetworkInfo[] getAllNetworkInfo() {
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        enforceAccessPermission();
4185154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt        NetworkInfo[] result = new NetworkInfo[mNetworksDefined];
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int i = 0;
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (NetworkStateTracker t : mNetTrackers) {
4215154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            if(t != null) result[i++] = t.getNetworkInfo();
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean setRadios(boolean turnOn) {
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean result = true;
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        enforceChangePermission();
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (NetworkStateTracker t : mNetTrackers) {
4305154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            if (t != null) result = t.setRadio(turnOn) && result;
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean setRadio(int netType, boolean turnOn) {
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        enforceChangePermission();
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!ConnectivityManager.isNetworkTypeValid(netType)) {
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NetworkStateTracker tracker = mNetTrackers[netType];
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return tracker != null && tracker.setRadio(turnOn);
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4449c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt    /**
4459c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt     * Used to notice when the calling process dies so we can self-expire
4469c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt     *
4479c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt     * Also used to know if the process has cleaned up after itself when
4489c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt     * our auto-expire timer goes off.  The timer has a link to an object.
4499c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt     *
4509c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt     */
45142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private class FeatureUser implements IBinder.DeathRecipient {
45242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        int mNetworkType;
45342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        String mFeature;
45442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        IBinder mBinder;
45542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        int mPid;
45642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        int mUid;
457b928535902b204ac3ec25f161352786842248767Robert Greenwalt        long mCreateTime;
45842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
45942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        FeatureUser(int type, String feature, IBinder binder) {
46042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            super();
46142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mNetworkType = type;
46242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mFeature = feature;
46342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mBinder = binder;
46442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mPid = getCallingPid();
46542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mUid = getCallingUid();
466b928535902b204ac3ec25f161352786842248767Robert Greenwalt            mCreateTime = System.currentTimeMillis();
4679c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt
46842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            try {
46942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                mBinder.linkToDeath(this, 0);
47042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } catch (RemoteException e) {
47142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                binderDied();
47242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
47342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
47442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
47542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        void unlinkDeathRecipient() {
47642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mBinder.unlinkToDeath(this, 0);
47742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
47842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
47942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        public void binderDied() {
48042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            Log.d(TAG, "ConnectivityService FeatureUser binderDied(" +
481b928535902b204ac3ec25f161352786842248767Robert Greenwalt                    mNetworkType + ", " + mFeature + ", " + mBinder + "), created " +
482b928535902b204ac3ec25f161352786842248767Robert Greenwalt                    (System.currentTimeMillis() - mCreateTime) + " mSec ago");
4839c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            stopUsingNetworkFeature(this, false);
48442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
48542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
4869c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        public void expire() {
4879c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            Log.d(TAG, "ConnectivityService FeatureUser expire(" +
488b928535902b204ac3ec25f161352786842248767Robert Greenwalt                    mNetworkType + ", " + mFeature + ", " + mBinder +"), created " +
489b928535902b204ac3ec25f161352786842248767Robert Greenwalt                    (System.currentTimeMillis() - mCreateTime) + " mSec ago");
4909c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            stopUsingNetworkFeature(this, false);
4919c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        }
492b928535902b204ac3ec25f161352786842248767Robert Greenwalt
493b928535902b204ac3ec25f161352786842248767Robert Greenwalt        public String toString() {
494b928535902b204ac3ec25f161352786842248767Robert Greenwalt            return "FeatureUser("+mNetworkType+","+mFeature+","+mPid+","+mUid+"), created " +
495b928535902b204ac3ec25f161352786842248767Robert Greenwalt                    (System.currentTimeMillis() - mCreateTime) + " mSec ago";
496b928535902b204ac3ec25f161352786842248767Robert Greenwalt        }
49742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    }
49842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
4999c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt    // javadoc from interface
50042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    public int startUsingNetworkFeature(int networkType, String feature,
50142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            IBinder binder) {
50242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (DBG) {
50342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            Log.d(TAG, "startUsingNetworkFeature for net " + networkType +
50442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    ": " + feature);
50542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        enforceChangePermission();
5075154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt        if (!ConnectivityManager.isNetworkTypeValid(networkType) ||
5085154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                mNetAttributes[networkType] == null) {
50942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            return Phone.APN_REQUEST_FAILED;
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
51142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
5129c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        FeatureUser f = new FeatureUser(networkType, feature, binder);
51342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
51442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        // TODO - move this into the MobileDataStateTracker
51542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        int usedNetworkType = networkType;
51642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if(networkType == ConnectivityManager.TYPE_MOBILE) {
51742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
51842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
51942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
52042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
52142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN)) {
52242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
52342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
52442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
52542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
52642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
52742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        NetworkStateTracker network = mNetTrackers[usedNetworkType];
52842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (network != null) {
52942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (usedNetworkType != networkType) {
53042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                Integer currentPid = new Integer(getCallingPid());
53142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
53242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                NetworkStateTracker radio = mNetTrackers[networkType];
53342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                NetworkInfo ni = network.getNetworkInfo();
53442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
53542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (ni.isAvailable() == false) {
53642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if (DBG) Log.d(TAG, "special network not available");
53742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    return Phone.APN_TYPE_NOT_AVAILABLE;
53842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
53942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
5409c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                synchronized(this) {
5419c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                    mFeatureUsers.add(f);
5429c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                    if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
5439c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                        // this gets used for per-pid dns when connected
5449c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                        mNetRequestersPids[usedNetworkType].add(currentPid);
5459c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                    }
54642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
5479c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                mHandler.sendMessageDelayed(mHandler.obtainMessage(
5489c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                        NetworkStateTracker.EVENT_RESTORE_DEFAULT_NETWORK,
5499c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                        f), getRestoreDefaultNetworkDelay());
5509c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt
55142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
552a64bf834ffa677405af1c87c9f53eed0cd3853ceRobert Greenwalt                if ((ni.isConnectedOrConnecting() == true) &&
553a64bf834ffa677405af1c87c9f53eed0cd3853ceRobert Greenwalt                        !network.isTeardownRequested()) {
55442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if (ni.isConnected() == true) {
55542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        // add the pid-specific dns
55642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        handleDnsConfigurationChange();
55742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        if (DBG) Log.d(TAG, "special network already active");
55842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        return Phone.APN_ALREADY_ACTIVE;
55942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
56042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if (DBG) Log.d(TAG, "special network already connecting");
56142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    return Phone.APN_REQUEST_STARTED;
56242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
56342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
56442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                // check if the radio in play can make another contact
56542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                // assume if cannot for now
56642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
56742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (DBG) Log.d(TAG, "reconnecting to special network");
56842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                network.reconnect();
56942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                return Phone.APN_REQUEST_STARTED;
57042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else {
5719c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                synchronized(this) {
5729c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                    mFeatureUsers.add(f);
5739c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                }
5749c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                mHandler.sendMessageDelayed(mHandler.obtainMessage(
5759c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                        NetworkStateTracker.EVENT_RESTORE_DEFAULT_NETWORK,
5769c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                        f), getRestoreDefaultNetworkDelay());
5779c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt
57842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                return network.startUsingNetworkFeature(feature,
57942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        getCallingPid(), getCallingUid());
58042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
58242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        return Phone.APN_TYPE_NOT_AVAILABLE;
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5859c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt    // javadoc from interface
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int stopUsingNetworkFeature(int networkType, String feature) {
587b8f16340b531809aa08cb73c55ddadd5f94de080Robert Greenwalt        enforceChangePermission();
588b8f16340b531809aa08cb73c55ddadd5f94de080Robert Greenwalt
5899c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        int pid = getCallingPid();
5909c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        int uid = getCallingUid();
5919c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt
5929c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        FeatureUser u = null;
5939c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        boolean found = false;
5949c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt
5959c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        synchronized(this) {
5969c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            for (int i = 0; i < mFeatureUsers.size() ; i++) {
5979c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                u = (FeatureUser)mFeatureUsers.get(i);
5989c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                if (uid == u.mUid && pid == u.mPid &&
5999c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                        networkType == u.mNetworkType &&
6009c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                        TextUtils.equals(feature, u.mFeature)) {
6019c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                    found = true;
6029c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                    break;
6039c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                }
6049c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            }
6059c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        }
6069c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        if (found && u != null) {
6079c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            // stop regardless of how many other time this proc had called start
6089c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            return stopUsingNetworkFeature(u, true);
6099c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        } else {
6109c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            // none found!
611b928535902b204ac3ec25f161352786842248767Robert Greenwalt            if (DBG) Log.d(TAG, "ignoring stopUsingNetworkFeature - not a live request");
6129c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            return 1;
6139c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        }
61442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    }
61542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
6169c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt    private int stopUsingNetworkFeature(FeatureUser u, boolean ignoreDups) {
6179c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        int networkType = u.mNetworkType;
6189c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        String feature = u.mFeature;
6199c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        int pid = u.mPid;
6209c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        int uid = u.mUid;
6219c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt
6229c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        NetworkStateTracker tracker = null;
6239c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        boolean callTeardown = false;  // used to carry our decision outside of sync block
6249c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt
62542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (DBG) {
62642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            Log.d(TAG, "stopUsingNetworkFeature for net " + networkType +
62742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    ": " + feature);
62842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
629b8f16340b531809aa08cb73c55ddadd5f94de080Robert Greenwalt
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
63342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
6349c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        // need to link the mFeatureUsers list with the mNetRequestersPids state in this
6359c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        // sync block
6369c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        synchronized(this) {
6379c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            // check if this process still has an outstanding start request
6389c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            if (!mFeatureUsers.contains(u)) {
6399c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                return 1;
6409c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            }
6419c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            u.unlinkDeathRecipient();
6429c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            mFeatureUsers.remove(mFeatureUsers.indexOf(u));
6439c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            // If we care about duplicate requests, check for that here.
6449c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            //
6459c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            // This is done to support the extension of a request - the app
6469c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            // can request we start the network feature again and renew the
6479c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            // auto-shutoff delay.  Normal "stop" calls from the app though
6489c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            // do not pay attention to duplicate requests - in effect the
6499c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            // API does not refcount and a single stop will counter multiple starts.
6509c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            if (ignoreDups == false) {
6519c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                for (int i = 0; i < mFeatureUsers.size() ; i++) {
6529c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                    FeatureUser x = (FeatureUser)mFeatureUsers.get(i);
6539c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                    if (x.mUid == u.mUid && x.mPid == u.mPid &&
6549c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                            x.mNetworkType == u.mNetworkType &&
6559c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                            TextUtils.equals(x.mFeature, u.mFeature)) {
656b928535902b204ac3ec25f161352786842248767Robert Greenwalt                        if (DBG) Log.d(TAG, "ignoring stopUsingNetworkFeature as dup is found");
6579c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                        return 1;
6589c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                    }
65942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
66042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
66142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
6629c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            // TODO - move to MobileDataStateTracker
6639c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            int usedNetworkType = networkType;
6649c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            if (networkType == ConnectivityManager.TYPE_MOBILE) {
6659c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
6669c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                    usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
6679c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
6689c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                    usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
6699c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN)) {
6709c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                    usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
6719c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
6729c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                    usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
6739c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                }
67442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
6759c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            tracker =  mNetTrackers[usedNetworkType];
6765154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            if (tracker == null) {
6775154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                return -1;
6785154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            }
6795154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            if (usedNetworkType != networkType) {
6809c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                Integer currentPid = new Integer(pid);
6819c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                mNetRequestersPids[usedNetworkType].remove(currentPid);
682421c72b6773582dd1473ace44c42d4e0ee1287e3Robert Greenwalt                reassessPidDns(pid, true);
6839c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                if (mNetRequestersPids[usedNetworkType].size() != 0) {
6849c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                    if (DBG) Log.d(TAG, "not tearing down special network - " +
6859c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                           "others still using it");
6869c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                    return 1;
6879c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                }
6889c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                callTeardown = true;
68942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
6909c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        }
69142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
6929c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt        if (callTeardown) {
69342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            tracker.teardown();
69442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            return 1;
69542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        } else {
6969c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt            // do it the old fashioned way
69742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            return tracker.stopUsingNetworkFeature(feature, pid, uid);
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Ensure that a network route exists to deliver traffic to the specified
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * host via the specified network interface.
70486e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * @param networkType the type of the network over which traffic to the
70586e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * specified host is to be routed
70686e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * @param hostAddress the IP address of the host to which the route is
70786e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * desired
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return {@code true} on success, {@code false} on failure
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requestRouteToHost(int networkType, int hostAddress) {
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        enforceChangePermission();
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NetworkStateTracker tracker = mNetTrackers[networkType];
7168206ff30c23c76851bebc8d72a65e65b0f7f9a29Robert Greenwalt
7175154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt        if (tracker == null || !tracker.getNetworkInfo().isConnected() ||
7185154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                tracker.isTeardownRequested()) {
7198206ff30c23c76851bebc8d72a65e65b0f7f9a29Robert Greenwalt            if (DBG) {
7205154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                Log.d(TAG, "requestRouteToHost on down network (" + networkType + ") - dropped");
7218206ff30c23c76851bebc8d72a65e65b0f7f9a29Robert Greenwalt            }
7228206ff30c23c76851bebc8d72a65e65b0f7f9a29Robert Greenwalt            return false;
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7248206ff30c23c76851bebc8d72a65e65b0f7f9a29Robert Greenwalt        return tracker.requestRouteToHost(hostAddress);
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see ConnectivityManager#getBackgroundDataSetting()
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean getBackgroundDataSetting() {
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Settings.Secure.getInt(mContext.getContentResolver(),
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Settings.Secure.BACKGROUND_DATA, 1) == 1;
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
73486e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see ConnectivityManager#setBackgroundDataSetting(boolean)
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setBackgroundDataSetting(boolean allowBackgroundDataUsage) {
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                android.Manifest.permission.CHANGE_BACKGROUND_DATA_SETTING,
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                "ConnectivityService");
74286e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (getBackgroundDataSetting() == allowBackgroundDataUsage) return;
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Settings.Secure.putInt(mContext.getContentResolver(),
74686e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                Settings.Secure.BACKGROUND_DATA,
74786e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                allowBackgroundDataUsage ? 1 : 0);
74886e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Intent broadcast = new Intent(
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.sendBroadcast(broadcast);
75286e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt    }
75386e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getNumConnectedNetworks() {
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int numConnectedNets = 0;
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (NetworkStateTracker nt : mNetTrackers) {
7585154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt            if (nt != null && nt.getNetworkInfo().isConnected() &&
75986e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    !nt.isTeardownRequested()) {
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ++numConnectedNets;
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return numConnectedNets;
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void enforceAccessPermission() {
76786e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt        mContext.enforceCallingOrSelfPermission(
76886e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                android.Manifest.permission.ACCESS_NETWORK_STATE,
76986e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                "ConnectivityService");
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void enforceChangePermission() {
77386e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt        mContext.enforceCallingOrSelfPermission(
77486e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                android.Manifest.permission.CHANGE_NETWORK_STATE,
77586e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                "ConnectivityService");
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
77986e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * Handle a {@code DISCONNECTED} event. If this pertains to the non-active
78086e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * network, we ignore it. If it is for the active network, we send out a
78186e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * broadcast. But first, we check whether it might be possible to connect
78286e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt     * to a different network.
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param info the {@code NetworkInfo} for the network
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void handleDisconnect(NetworkInfo info) {
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
78742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        int prevNetType = info.getType();
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
78942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        mNetTrackers[prevNetType].setTeardownRequested(false);
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * If the disconnected network is not the active one, then don't report
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * this as a loss of connectivity. What probably happened is that we're
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * getting the disconnect for a network that we explicitly disabled
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * in accordance with network preference policies.
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
79642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (!mNetAttributes[prevNetType].isDefault()) {
79742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            List pids = mNetRequestersPids[prevNetType];
79842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            for (int i = 0; i<pids.size(); i++) {
79942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                Integer pid = (Integer)pids.get(i);
80042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                // will remove them because the net's no longer connected
80142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                // need to do this now as only now do we know the pids and
80242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                // can properly null things that are no longer referenced.
80342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                reassessPidDns(pid.intValue(), false);
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
8081c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info.isFailover()) {
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            info.setFailover(false);
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info.getReason() != null) {
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info.getExtraInfo() != null) {
81886e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt            intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
81986e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    info.getExtraInfo());
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
82142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
82242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        /*
82342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt         * If this is a default network, check if other defaults are available
82442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt         * or active
82542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt         */
82642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        NetworkStateTracker newNet = null;
82742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (mNetAttributes[prevNetType].isDefault()) {
82842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (mActiveDefaultNetwork == prevNetType) {
82942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                mActiveDefaultNetwork = -1;
83042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
83142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
83242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            int newType = -1;
83342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            int newPriority = -1;
83442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            for (int checkType=0; checkType <=
83542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
8365154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                if (checkType == prevNetType) continue;
8375154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                if (mNetAttributes[checkType] == null) continue;
83842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (mNetAttributes[checkType].isDefault()) {
83942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    /* TODO - if we have multiple nets we could use
84042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                     * we may want to put more thought into which we choose
84142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                     */
84242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if (checkType == mNetworkPreference) {
84342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        newType = checkType;
84442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        break;
84542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
8465154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                    if (mNetAttributes[checkType].mPriority > newPriority) {
84742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        newType = checkType;
8485154ae7665743b114c71f90dcc577dc50c63b398Robert Greenwalt                        newPriority = mNetAttributes[newType].mPriority;
84942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
85042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
85142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
85242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
85342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (newType != -1) {
85442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                newNet = mNetTrackers[newType];
85542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                /**
85642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                 * See if the other network is available to fail over to.
85742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                 * If is not available, we enable it anyway, so that it
85842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                 * will be able to connect when it does become available,
85942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                 * but we report a total loss of connectivity rather than
86042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                 * report that we are attempting to fail over.
86142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                 */
86242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (newNet.isAvailable()) {
86342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    NetworkInfo switchTo = newNet.getNetworkInfo();
86442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    switchTo.setFailover(true);
865a64bf834ffa677405af1c87c9f53eed0cd3853ceRobert Greenwalt                    if (!switchTo.isConnectedOrConnecting() ||
866a64bf834ffa677405af1c87c9f53eed0cd3853ceRobert Greenwalt                            newNet.isTeardownRequested()) {
86742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        newNet.reconnect();
86842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
86942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if (DBG) {
87042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        if (switchTo.isConnected()) {
87142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            Log.v(TAG, "Switching to already connected " +
87242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                                    switchTo.getTypeName());
87342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        } else {
87442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            Log.v(TAG, "Attempting to switch to " +
87542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                                    switchTo.getTypeName());
87642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        }
87742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
87842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    intent.putExtra(ConnectivityManager.
87942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            EXTRA_OTHER_NETWORK_INFO, switchTo);
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
881c7d2530d52e9c188392b118caea64673dbbad45cRobert Greenwalt                    intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,
882c7d2530d52e9c188392b118caea64673dbbad45cRobert Greenwalt                            true);
88342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    newNet.reconnect();
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
88542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else {
88642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,
88742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        true);
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
89042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
89142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        // do this before we broadcast the change
89242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        handleConnectivityChange();
89342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
8940f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood        sendStickyBroadcast(intent);
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
89686e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt         * If the failover network is already connected, then immediately send
89786e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt         * out a followup broadcast indicating successful failover
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
89942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (newNet != null && newNet.getNetworkInfo().isConnected())
90042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            sendConnectedBroadcast(newNet.getNetworkInfo());
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void sendConnectedBroadcast(NetworkInfo info) {
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
9051c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info.isFailover()) {
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            info.setFailover(false);
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info.getReason() != null) {
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info.getExtraInfo() != null) {
91586e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt            intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
91686e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    info.getExtraInfo());
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9180f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood        sendStickyBroadcast(intent);
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when an attempt to fail over to another network has failed.
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param info the {@link NetworkInfo} for the failed network
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void handleConnectionFailure(NetworkInfo info) {
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNetTrackers[info.getType()].setTeardownRequested(false);
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
92842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        String reason = info.getReason();
92942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        String extraInfo = info.getExtraInfo();
93042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
93142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (DBG) {
93242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            String reasonText;
93342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (reason == null) {
93442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                reasonText = ".";
93542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else {
93642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                reasonText = " (" + reason + ").";
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
93842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            Log.v(TAG, "Attempt to connect to " + info.getTypeName() +
93942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    " failed" + reasonText);
94042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
94186e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
94242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
9431c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
94442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
94542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (getActiveNetworkInfo() == null) {
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
94842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (reason != null) {
94942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            intent.putExtra(ConnectivityManager.EXTRA_REASON, reason);
95042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
95142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (extraInfo != null) {
95242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, extraInfo);
95342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
95442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (info.isFailover()) {
95542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
95642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            info.setFailover(false);
95742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
9580f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood        sendStickyBroadcast(intent);
9590f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood    }
9600f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood
9610f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood    private void sendStickyBroadcast(Intent intent) {
9620f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood        synchronized(this) {
9631c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn            if (!mSystemReady) {
9641c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn                mInitialBroadcast = new Intent(intent);
9650f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood            }
9661c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
9671c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn            mContext.sendStickyBroadcast(intent);
9680f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood        }
9690f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood    }
9700f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood
9710f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood    void systemReady() {
9720f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood        synchronized(this) {
9730f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood            mSystemReady = true;
9741c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn            if (mInitialBroadcast != null) {
9751c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn                mContext.sendStickyBroadcast(mInitialBroadcast);
9761c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn                mInitialBroadcast = null;
9770f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood            }
9780f79b54c3a0b4141b1da38fa301571a89e165632Mike Lockwood        }
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void handleConnect(NetworkInfo info) {
98242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        int type = info.getType();
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // snapshot isFailover, because sendConnectedBroadcast() resets it
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean isFailover = info.isFailover();
98642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        NetworkStateTracker thisNet = mNetTrackers[type];
98742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
98842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        // if this is a default net and other default is running
98942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        // kill the one not preferred
99042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (mNetAttributes[type].isDefault()) {
99142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
99242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if ((type != mNetworkPreference &&
99342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        mNetAttributes[mActiveDefaultNetwork].mPriority >
99442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        mNetAttributes[type].mPriority) ||
99542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        mNetworkPreference == mActiveDefaultNetwork) {
99642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        // don't accept this one
99742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        if (DBG) Log.v(TAG, "Not broadcasting CONNECT_ACTION " +
99842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                                "to torn down network " + info.getTypeName());
99942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        teardown(thisNet);
100042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        return;
100142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                } else {
100242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    // tear down the other
100342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    NetworkStateTracker otherNet =
100442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            mNetTrackers[mActiveDefaultNetwork];
100542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if (DBG) Log.v(TAG, "Policy requires " +
100642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            otherNet.getNetworkInfo().getTypeName() +
100742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            " teardown");
100842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if (!teardown(otherNet)) {
100942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        Log.e(TAG, "Network declined teardown request");
101042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        return;
101142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
101242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if (isFailover) {
101342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        otherNet.releaseWakeLock();
101442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
101542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
101742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            mActiveDefaultNetwork = type;
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
101942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        thisNet.setTeardownRequested(false);
102042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        thisNet.updateNetworkSettings();
102142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        handleConnectivityChange();
102242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        sendConnectedBroadcast(info);
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void handleScanResultsAvailable(NetworkInfo info) {
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int networkType = info.getType();
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (networkType != ConnectivityManager.TYPE_WIFI) {
102886e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt            if (DBG) Log.v(TAG, "Got ScanResultsAvailable for " +
102986e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    info.getTypeName() + " network. Don't know how to handle.");
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
103186e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNetTrackers[networkType].interpretScanResultsAvailable();
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
103586e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt    private void handleNotificationChange(boolean visible, int id,
103686e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt            Notification notification) {
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NotificationManager notificationManager = (NotificationManager) mContext
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                .getSystemService(Context.NOTIFICATION_SERVICE);
103986e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (visible) {
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notificationManager.notify(id, notification);
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notificationManager.cancel(id);
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * After any kind of change in the connectivity state of any network,
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * make sure that anything that depends on the connectivity state of
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * more than one network is set up correctly. We're mainly concerned
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * with making sure that the list of DNS servers is set up  according
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to which networks are connected, and ensuring that the right routing
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * table entries exist.
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void handleConnectivityChange() {
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
105742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt         * If a non-default network is enabled, add the host routes that
10581ef95f9eed610897b46a00f51a7cd7944ef26e62Robert Greenwalt         * will allow it's DNS servers to be accessed.  Only
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * If both mobile and wifi are enabled, add the host routes that
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * will allow MMS traffic to pass on the mobile network. But
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * remove the default route for the mobile network, so that there
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * will be only one default route, to ensure that all traffic
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * except MMS will travel via Wi-Fi.
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
106542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        handleDnsConfigurationChange();
106642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
106742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        for (int netType : mPriorityList) {
106842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
106942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (mNetAttributes[netType].isDefault()) {
107042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    mNetTrackers[netType].addDefaultRoute();
107142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                } else {
107242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    mNetTrackers[netType].addPrivateDnsRoutes();
107342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
107442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } else {
107542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (mNetAttributes[netType].isDefault()) {
107642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    mNetTrackers[netType].removeDefaultRoute();
107742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                } else {
107842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    mNetTrackers[netType].removePrivateDnsRoutes();
107942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
108042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
108442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    /**
108542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt     * Adjust the per-process dns entries (net.dns<x>.<pid>) based
108642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt     * on the highest priority active net which this process requested.
108742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt     * If there aren't any, clear it out
108842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt     */
108942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private void reassessPidDns(int myPid, boolean doBump)
109042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    {
109142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (DBG) Log.d(TAG, "reassessPidDns for pid " + myPid);
109242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        for(int i : mPriorityList) {
109342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (mNetAttributes[i].isDefault()) {
109442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                continue;
109542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
109642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            NetworkStateTracker nt = mNetTrackers[i];
109742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (nt.getNetworkInfo().isConnected() &&
109842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    !nt.isTeardownRequested()) {
109942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                List pids = mNetRequestersPids[i];
110042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                for (int j=0; j<pids.size(); j++) {
110142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    Integer pid = (Integer)pids.get(j);
110242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if (pid.intValue() == myPid) {
110342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        String[] dnsList = nt.getNameServers();
110442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        writePidDns(dnsList, myPid);
110542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        if (doBump) {
110642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            bumpDns();
110742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        }
110842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        return;
110942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
111042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
111142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt           }
111242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
111342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        // nothing found - delete
111442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        for (int i = 1; ; i++) {
111542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            String prop = "net.dns" + i + "." + myPid;
111642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (SystemProperties.get(prop).length() == 0) {
111742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (doBump) {
111842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    bumpDns();
111942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                }
112042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                return;
112142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
112242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            SystemProperties.set(prop, "");
112342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
112442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    }
112542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
112642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private void writePidDns(String[] dnsList, int pid) {
112742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        int j = 1;
112842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        for (String dns : dnsList) {
112942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (dns != null && !TextUtils.equals(dns, "0.0.0.0")) {
113042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                SystemProperties.set("net.dns" + j++ + "." + pid, dns);
113142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
113242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
113342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    }
113442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
113542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private void bumpDns() {
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
113742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt         * Bump the property that tells the name resolver library to reread
113842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt         * the DNS server list from the properties.
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
114042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        String propVal = SystemProperties.get("net.dnschange");
114142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        int n = 0;
114242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if (propVal.length() != 0) {
114342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            try {
114442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                n = Integer.parseInt(propVal);
114542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } catch (NumberFormatException e) {}
114642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        }
114742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        SystemProperties.set("net.dnschange", "" + (n+1));
114842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    }
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
115042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private void handleDnsConfigurationChange() {
115142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        // add default net's dns entries
115242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        for (int x = mPriorityList.length-1; x>= 0; x--) {
115342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            int netType = mPriorityList[x];
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            NetworkStateTracker nt = mNetTrackers[netType];
115542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            if (nt != null && nt.getNetworkInfo().isConnected() &&
115686e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    !nt.isTeardownRequested()) {
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String[] dnsList = nt.getNameServers();
115842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                if (mNetAttributes[netType].isDefault()) {
115942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    int j = 1;
116042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    for (String dns : dnsList) {
116142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        if (dns != null && !TextUtils.equals(dns, "0.0.0.0")) {
11621ef95f9eed610897b46a00f51a7cd7944ef26e62Robert Greenwalt                            if (DBG) {
11631ef95f9eed610897b46a00f51a7cd7944ef26e62Robert Greenwalt                                Log.d(TAG, "adding dns " + dns + " for " +
11641ef95f9eed610897b46a00f51a7cd7944ef26e62Robert Greenwalt                                        nt.getNetworkInfo().getTypeName());
11651ef95f9eed610897b46a00f51a7cd7944ef26e62Robert Greenwalt                            }
116642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                            SystemProperties.set("net.dns" + j++, dns);
116742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        }
116842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
116942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    for (int k=j ; k<mNumDnsEntries; k++) {
1170b06324a5c1af11b0fef76bdafa569a60498a93d2Robert Greenwalt                        if (DBG) Log.d(TAG, "erasing net.dns" + k);
1171b06324a5c1af11b0fef76bdafa569a60498a93d2Robert Greenwalt                        SystemProperties.set("net.dns" + k, "");
117242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    }
117342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    mNumDnsEntries = j;
117442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                } else {
117542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    // set per-pid dns for attached secondary nets
117642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    List pids = mNetRequestersPids[netType];
117742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    for (int y=0; y< pids.size(); y++) {
117842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        Integer pid = (Integer)pids.get(y);
117942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                        writePidDns(dnsList, pid.intValue());
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
118442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
118542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        bumpDns();
118642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    }
118742acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt
118842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    private int getRestoreDefaultNetworkDelay() {
118942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        String restoreDefaultNetworkDelayStr = SystemProperties.get(
119042acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                NETWORK_RESTORE_DELAY_PROP_NAME);
119142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        if(restoreDefaultNetworkDelayStr != null &&
119242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                restoreDefaultNetworkDelayStr.length() != 0) {
119342acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            try {
119442acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                return Integer.valueOf(restoreDefaultNetworkDelayStr);
119542acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            } catch (NumberFormatException e) {
119642acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
119842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt        return RESTORE_DEFAULT_NETWORK_DELAY;
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
120386e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt        if (mContext.checkCallingOrSelfPermission(
120486e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                android.Manifest.permission.DUMP)
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
120686e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt            pw.println("Permission Denial: can't dump ConnectivityService " +
120786e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    "from from pid=" + Binder.getCallingPid() + ", uid=" +
120886e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    Binder.getCallingUid());
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pw.println();
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (NetworkStateTracker nst : mNetTrackers) {
1213b928535902b204ac3ec25f161352786842248767Robert Greenwalt            if (nst != null) {
1214b928535902b204ac3ec25f161352786842248767Robert Greenwalt                if (nst.getNetworkInfo().isConnected()) {
1215b928535902b204ac3ec25f161352786842248767Robert Greenwalt                    pw.println("Active network: " + nst.getNetworkInfo().
1216b928535902b204ac3ec25f161352786842248767Robert Greenwalt                            getTypeName());
1217b928535902b204ac3ec25f161352786842248767Robert Greenwalt                }
1218b928535902b204ac3ec25f161352786842248767Robert Greenwalt                pw.println(nst.getNetworkInfo());
1219b928535902b204ac3ec25f161352786842248767Robert Greenwalt                pw.println(nst);
1220b928535902b204ac3ec25f161352786842248767Robert Greenwalt                pw.println();
1221b928535902b204ac3ec25f161352786842248767Robert Greenwalt            }
1222b928535902b204ac3ec25f161352786842248767Robert Greenwalt        }
1223b928535902b204ac3ec25f161352786842248767Robert Greenwalt
1224b928535902b204ac3ec25f161352786842248767Robert Greenwalt        pw.println("Network Requester Pids:");
1225b928535902b204ac3ec25f161352786842248767Robert Greenwalt        for (int net : mPriorityList) {
1226b928535902b204ac3ec25f161352786842248767Robert Greenwalt            String pidString = net + ": ";
1227b928535902b204ac3ec25f161352786842248767Robert Greenwalt            for (Object pid : mNetRequestersPids[net]) {
1228b928535902b204ac3ec25f161352786842248767Robert Greenwalt                pidString = pidString + pid.toString() + ", ";
122942acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt            }
1230b928535902b204ac3ec25f161352786842248767Robert Greenwalt            pw.println(pidString);
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1232b928535902b204ac3ec25f161352786842248767Robert Greenwalt        pw.println();
1233b928535902b204ac3ec25f161352786842248767Robert Greenwalt
1234b928535902b204ac3ec25f161352786842248767Robert Greenwalt        pw.println("FeatureUsers:");
1235b928535902b204ac3ec25f161352786842248767Robert Greenwalt        for (Object requester : mFeatureUsers) {
1236b928535902b204ac3ec25f161352786842248767Robert Greenwalt            pw.println(requester.toString());
1237b928535902b204ac3ec25f161352786842248767Robert Greenwalt        }
1238b928535902b204ac3ec25f161352786842248767Robert Greenwalt        pw.println();
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
124142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt    // must be stateless - things change under us.
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class MyHandler extends Handler {
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void handleMessage(Message msg) {
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            NetworkInfo info;
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (msg.what) {
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case NetworkStateTracker.EVENT_STATE_CHANGED:
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    info = (NetworkInfo) msg.obj;
1249511288a04639859a6d9bbfedfa2f2b4d7d2c3e88Robert Greenwalt                    int type = info.getType();
1250511288a04639859a6d9bbfedfa2f2b4d7d2c3e88Robert Greenwalt                    NetworkInfo.State state = info.getState();
1251511288a04639859a6d9bbfedfa2f2b4d7d2c3e88Robert Greenwalt                    if(mNetAttributes[type].mLastState == state) {
1252511288a04639859a6d9bbfedfa2f2b4d7d2c3e88Robert Greenwalt                        if (DBG) {
1253511288a04639859a6d9bbfedfa2f2b4d7d2c3e88Robert Greenwalt                            // TODO - remove this after we validate the dropping doesn't break anything
1254511288a04639859a6d9bbfedfa2f2b4d7d2c3e88Robert Greenwalt                            Log.d(TAG, "Dropping ConnectivityChange for " +
1255511288a04639859a6d9bbfedfa2f2b4d7d2c3e88Robert Greenwalt                                    info.getTypeName() +": " +
1256511288a04639859a6d9bbfedfa2f2b4d7d2c3e88Robert Greenwalt                                    state + "/" + info.getDetailedState());
1257511288a04639859a6d9bbfedfa2f2b4d7d2c3e88Robert Greenwalt                        }
1258511288a04639859a6d9bbfedfa2f2b4d7d2c3e88Robert Greenwalt                        return;
1259511288a04639859a6d9bbfedfa2f2b4d7d2c3e88Robert Greenwalt                    }
1260511288a04639859a6d9bbfedfa2f2b4d7d2c3e88Robert Greenwalt                    mNetAttributes[type].mLastState = state;
1261511288a04639859a6d9bbfedfa2f2b4d7d2c3e88Robert Greenwalt
126242acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    if (DBG) Log.d(TAG, "ConnectivityChange for " +
126386e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                            info.getTypeName() + ": " +
1264511288a04639859a6d9bbfedfa2f2b4d7d2c3e88Robert Greenwalt                            state + "/" + info.getDetailedState());
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Connectivity state changed:
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // [31-13] Reserved for future use
126886e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    // [12-9] Network subtype (for mobile network, as defined
126986e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    //         by TelephonyManager)
127086e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    // [8-3] Detailed state ordinal (as defined by
127186e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    //         NetworkInfo.DetailedState)
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // [2-0] Network type (as defined by ConnectivityManager)
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    int eventLogParam = (info.getType() & 0x7) |
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            ((info.getDetailedState().ordinal() & 0x3f) << 3) |
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (info.getSubtype() << 9);
1276ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker                    EventLog.writeEvent(EventLogTags.CONNECTIVITY_STATE_CHANGED,
127786e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                            eventLogParam);
127886e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
127986e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    if (info.getDetailedState() ==
128086e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                            NetworkInfo.DetailedState.FAILED) {
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        handleConnectionFailure(info);
1282511288a04639859a6d9bbfedfa2f2b4d7d2c3e88Robert Greenwalt                    } else if (state == NetworkInfo.State.DISCONNECTED) {
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        handleDisconnect(info);
1284511288a04639859a6d9bbfedfa2f2b4d7d2c3e88Robert Greenwalt                    } else if (state == NetworkInfo.State.SUSPENDED) {
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // TODO: need to think this over.
128686e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                        // the logic here is, handle SUSPENDED the same as
128786e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                        // DISCONNECTED. The only difference being we are
128886e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                        // broadcasting an intent with NetworkInfo that's
128986e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                        // suspended. This allows the applications an
129086e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                        // opportunity to handle DISCONNECTED and SUSPENDED
129186e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                        // differently, or not.
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        handleDisconnect(info);
1293511288a04639859a6d9bbfedfa2f2b4d7d2c3e88Robert Greenwalt                    } else if (state == NetworkInfo.State.CONNECTED) {
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        handleConnect(info);
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case NetworkStateTracker.EVENT_SCAN_RESULTS_AVAILABLE:
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    info = (NetworkInfo) msg.obj;
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    handleScanResultsAvailable(info);
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
130286e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case NetworkStateTracker.EVENT_NOTIFICATION_CHANGED:
130486e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                    handleNotificationChange(msg.arg1 == 1, msg.arg2,
130586e9e55c54a3e07f6c9476d107db99131cefc5d7Robert Greenwalt                            (Notification) msg.obj);
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
130842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    handleDnsConfigurationChange();
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case NetworkStateTracker.EVENT_ROAMING_CHANGED:
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // fill me in
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case NetworkStateTracker.EVENT_NETWORK_SUBTYPE_CHANGED:
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // fill me in
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
131842acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                case NetworkStateTracker.EVENT_RESTORE_DEFAULT_NETWORK:
13199c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                    FeatureUser u = (FeatureUser)msg.obj;
13209c75d4af63f92806943a9fa9d942644bd601310eRobert Greenwalt                    u.expire();
132142acef37339afe6ac608c842f1637870ee9c4f6cRobert Greenwalt                    break;
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1326