120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti/*
220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * Copyright (C) 2014 The Android Open Source Project
320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti *
420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * Licensed under the Apache License, Version 2.0 (the "License");
520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * you may not use this file except in compliance with the License.
620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * You may obtain a copy of the License at
720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti *
820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti *      http://www.apache.org/licenses/LICENSE-2.0
920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti *
1020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * Unless required by applicable law or agreed to in writing, software
1120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * distributed under the License is distributed on an "AS IS" BASIS,
1220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * See the License for the specific language governing permissions and
1420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * limitations under the License.
1520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti */
1620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
1720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittipackage com.android.server.ethernet;
1820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
1920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.content.Context;
2020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.net.ConnectivityManager;
2120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.net.DhcpResults;
22a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kimimport android.net.EthernetManager;
23a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kimimport android.net.IEthernetServiceListener;
2420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.net.InterfaceConfiguration;
2520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.net.IpConfiguration;
2620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.net.IpConfiguration.IpAssignment;
2720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.net.IpConfiguration.ProxySettings;
2820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.net.LinkProperties;
2920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.net.NetworkAgent;
3020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.net.NetworkCapabilities;
310d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwaltimport android.net.NetworkFactory;
3220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.net.NetworkInfo;
3320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.net.NetworkInfo.DetailedState;
34a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kimimport android.net.NetworkUtils;
3541a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colittiimport android.net.StaticIpConfiguration;
3620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.os.Handler;
3720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.os.IBinder;
3820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.os.INetworkManagementService;
3920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.os.Looper;
40a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kimimport android.os.RemoteCallbackList;
4120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.os.RemoteException;
4220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.os.ServiceManager;
4320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.text.TextUtils;
4420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport android.util.Log;
4520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
46aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colittiimport com.android.internal.util.IndentingPrintWriter;
4720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colittiimport com.android.server.net.BaseNetworkObserver;
4820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
49aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colittiimport java.io.FileDescriptor;
50aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colittiimport java.io.PrintWriter;
5120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
5220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
5320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti/**
54044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti * Manages connectivity for an Ethernet interface.
55044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti *
56044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti * Ethernet Interfaces may be present at boot time or appear after boot (e.g.,
57044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti * for Ethernet adapters connected over USB). This class currently supports
58044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti * only one interface. When an interface appears on the system (or is present
59044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti * at boot time) this class will start tracking it and bring it up, and will
60044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti * attempt to connect when requested. Any other interfaces that subsequently
61044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti * appear will be ignored until the tracked interface disappears. Only
62044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti * interfaces whose names match the <code>config_ethernet_iface_regex</code>
63044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti * regular expression are tracked.
64044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti *
65044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti * This class reports a static network score of 70 when it is tracking an
66044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti * interface and that interface's link is up, and a score of 0 otherwise.
67044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti *
6820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti * @hide
6920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti */
700d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwaltclass EthernetNetworkFactory {
710d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt    private static final String NETWORK_TYPE = "Ethernet";
7220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private static final String TAG = "EthernetNetworkFactory";
7320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private static final int NETWORK_SCORE = 70;
7420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private static final boolean DBG = true;
7520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
76044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti    /** Tracks interface changes. Called from NetworkManagementService. */
7720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private InterfaceObserver mInterfaceObserver;
7820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
7920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    /** For static IP configuration */
8020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private EthernetManager mEthernetManager;
8120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
8220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    /** To set link state and configure IP addresses. */
8320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private INetworkManagementService mNMService;
8420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
8520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    /* To communicate with ConnectivityManager */
8620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private NetworkCapabilities mNetworkCapabilities;
8720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private NetworkAgent mNetworkAgent;
880d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt    private LocalNetworkFactory mFactory;
890d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt    private Context mContext;
9020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
91044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti    /** Product-dependent regular expression of interface names we track. */
9220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private static String mIfaceMatch = "";
9320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
94a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim    /** To notify Ethernet status. */
95a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim    private final RemoteCallbackList<IEthernetServiceListener> mListeners;
96a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim
97044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti    /** Data members. All accesses to these must be synchronized(this). */
9820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private static String mIface = "";
9920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private String mHwAddr;
10020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private static boolean mLinkUp;
10120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private NetworkInfo mNetworkInfo;
10220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private LinkProperties mLinkProperties;
10320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
104a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim    EthernetNetworkFactory(RemoteCallbackList<IEthernetServiceListener> listeners) {
10520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, "");
10620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        mLinkProperties = new LinkProperties();
10720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        initNetworkCapabilities();
108a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        mListeners = listeners;
10920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    }
11020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
1110d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt    private class LocalNetworkFactory extends NetworkFactory {
1120d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt        LocalNetworkFactory(String name, Context context, Looper looper) {
1130d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt            super(looper, context, name, new NetworkCapabilities());
1140d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt        }
1150d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt
1160d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt        protected void startNetwork() {
1170d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt            onRequestNetwork();
1180d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt        }
1190d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt        protected void stopNetwork() {
1200d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt        }
1210d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt    }
1220d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt
1230d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt
124044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti    /**
125044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti     * Updates interface state variables.
126044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti     * Called on link state changes or on startup.
127044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti     */
12820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private void updateInterfaceState(String iface, boolean up) {
12920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        if (!mIface.equals(iface)) {
13020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            return;
13120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        }
13220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        Log.d(TAG, "updateInterface: " + iface + " link " + (up ? "up" : "down"));
13320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
13420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        synchronized(this) {
13520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            mLinkUp = up;
13620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            mNetworkInfo.setIsAvailable(up);
137044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti            if (!up) {
138044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti                // Tell the agent we're disconnected. It will call disconnect().
139044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti                mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr);
140044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti            }
14120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            updateAgent();
142e3cbf2e7349dd366f33905784595e2e3a1cec245Robert Greenwalt            // set our score lower than any network could go
143e3cbf2e7349dd366f33905784595e2e3a1cec245Robert Greenwalt            // so we get dropped.  TODO - just unregister the factory
144e3cbf2e7349dd366f33905784595e2e3a1cec245Robert Greenwalt            // when link goes down.
1450d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt            mFactory.setScoreFilter(up ? NETWORK_SCORE : -1);
14620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        }
14720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    }
14820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
14920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private class InterfaceObserver extends BaseNetworkObserver {
15020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        @Override
15120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        public void interfaceLinkStateChanged(String iface, boolean up) {
15220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            updateInterfaceState(iface, up);
15320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        }
15420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
15520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        @Override
15620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        public void interfaceAdded(String iface) {
15720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            maybeTrackInterface(iface);
15820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        }
15920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
16020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        @Override
16120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        public void interfaceRemoved(String iface) {
16220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            stopTrackingInterface(iface);
16320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        }
16420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    }
16520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
16620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private void setInterfaceUp(String iface) {
16720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        // Bring up the interface so we get link status indications.
16820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        try {
16920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            mNMService.setInterfaceUp(iface);
17020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            String hwAddr = null;
17120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            InterfaceConfiguration config = mNMService.getInterfaceConfig(iface);
17220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
17320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            if (config == null) {
17420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                Log.e(TAG, "Null iterface config for " + iface + ". Bailing out.");
17520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                return;
17620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            }
17720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
17820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            synchronized (this) {
179a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim                if (!isTrackingInterface()) {
180a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim                    setInterfaceInfoLocked(iface, config.getHardwareAddress());
18120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                    mNetworkInfo.setIsAvailable(true);
18220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                    mNetworkInfo.setExtraInfo(mHwAddr);
18320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                } else {
18420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                    Log.e(TAG, "Interface unexpectedly changed from " + iface + " to " + mIface);
18520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                    mNMService.setInterfaceDown(iface);
18620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                }
18720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            }
18820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        } catch (RemoteException e) {
18920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            Log.e(TAG, "Error upping interface " + mIface + ": " + e);
19020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        }
19120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    }
19220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
19320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private boolean maybeTrackInterface(String iface) {
19420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        // If we don't already have an interface, and if this interface matches
19520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        // our regex, start tracking it.
196a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        if (!iface.matches(mIfaceMatch) || isTrackingInterface())
19720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            return false;
19820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
19920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        Log.d(TAG, "Started tracking interface " + iface);
20020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        setInterfaceUp(iface);
20120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        return true;
20220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    }
20320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
20420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private void stopTrackingInterface(String iface) {
20520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        if (!iface.equals(mIface))
20620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            return;
20720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
20820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        Log.d(TAG, "Stopped tracking interface " + iface);
20974d270d167ed6c3a6fa28e426da80d51a44a2af0Lorenzo Colitti        // TODO: Unify this codepath with stop().
21020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        synchronized (this) {
21174d270d167ed6c3a6fa28e426da80d51a44a2af0Lorenzo Colitti            NetworkUtils.stopDhcp(mIface);
212a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim            setInterfaceInfoLocked("", null);
21320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            mNetworkInfo.setExtraInfo(null);
21474d270d167ed6c3a6fa28e426da80d51a44a2af0Lorenzo Colitti            mLinkUp = false;
21574d270d167ed6c3a6fa28e426da80d51a44a2af0Lorenzo Colitti            mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr);
21674d270d167ed6c3a6fa28e426da80d51a44a2af0Lorenzo Colitti            updateAgent();
21774d270d167ed6c3a6fa28e426da80d51a44a2af0Lorenzo Colitti            mNetworkAgent = null;
218044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti            mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, "");
219044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti            mLinkProperties = new LinkProperties();
22020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        }
22120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    }
22220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
22341a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti    private boolean setStaticIpAddress(StaticIpConfiguration staticConfig) {
22441a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti        if (staticConfig.ipAddress != null &&
22541a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti                staticConfig.gateway != null &&
22641a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti                staticConfig.dnsServers.size() > 0) {
22741a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti            try {
22841a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti                Log.i(TAG, "Applying static IPv4 configuration to " + mIface + ": " + staticConfig);
22941a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti                InterfaceConfiguration config = mNMService.getInterfaceConfig(mIface);
23041a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti                config.setLinkAddress(staticConfig.ipAddress);
23141a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti                mNMService.setInterfaceConfig(mIface, config);
23241a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti                return true;
23341a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti            } catch(RemoteException|IllegalStateException e) {
23441a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti               Log.e(TAG, "Setting static IP address failed: " + e.getMessage());
23520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            }
23641a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti        } else {
23741a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti            Log.e(TAG, "Invalid static IP configuration.");
23820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        }
23941a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti        return false;
24020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    }
24120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
2420d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt    public void updateAgent() {
2430d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt        synchronized (EthernetNetworkFactory.this) {
2440d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt            if (mNetworkAgent == null) return;
2450d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt            if (DBG) {
2460d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt                Log.i(TAG, "Updating mNetworkAgent with: " +
2470d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt                      mNetworkCapabilities + ", " +
2480d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt                      mNetworkInfo + ", " +
2490d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt                      mLinkProperties);
2500d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt            }
2510d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt            mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
2520d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt            mNetworkAgent.sendNetworkInfo(mNetworkInfo);
2530d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt            mNetworkAgent.sendLinkProperties(mLinkProperties);
254e3cbf2e7349dd366f33905784595e2e3a1cec245Robert Greenwalt            // never set the network score below 0.
255e3cbf2e7349dd366f33905784595e2e3a1cec245Robert Greenwalt            mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : 0);
25620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        }
25720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    }
25820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
2590d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt    /* Called by the NetworkFactory on the handler thread. */
2600d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt    public void onRequestNetwork() {
2610d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt        // TODO: Handle DHCP renew.
26220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        Thread dhcpThread = new Thread(new Runnable() {
26320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            public void run() {
2640d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt                if (DBG) Log.i(TAG, "dhcpThread(+" + mIface + "): mNetworkInfo=" + mNetworkInfo);
26520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                LinkProperties linkProperties;
26620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
26720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                IpConfiguration config = mEthernetManager.getConfiguration();
26820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
26941a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti                if (config.getIpAssignment() == IpAssignment.STATIC) {
27041a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti                    if (!setStaticIpAddress(config.getStaticIpConfiguration())) {
27141a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti                        // We've already logged an error.
27241a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti                        return;
27341a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti                    }
27441a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti                    linkProperties = config.getStaticIpConfiguration().toLinkProperties(mIface);
27520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                } else {
2760d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt                    mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr);
2770d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt
27820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                    DhcpResults dhcpResults = new DhcpResults();
279044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti                    // TODO: Handle DHCP renewals better.
280044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti                    // In general runDhcp handles DHCP renewals for us, because
281044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti                    // the dhcp client stays running, but if the renewal fails,
282044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti                    // we will lose our IP address and connectivity without
283044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti                    // noticing.
28420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                    if (!NetworkUtils.runDhcp(mIface, dhcpResults)) {
28520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                        Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
286e3cbf2e7349dd366f33905784595e2e3a1cec245Robert Greenwalt                        // set our score lower than any network could go
287e3cbf2e7349dd366f33905784595e2e3a1cec245Robert Greenwalt                        // so we get dropped.
2880d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt                        mFactory.setScoreFilter(-1);
28920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                        return;
29020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                    }
29141a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti                    linkProperties = dhcpResults.toLinkProperties(mIface);
29220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                }
29341a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti                if (config.getProxySettings() == ProxySettings.STATIC ||
29441a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti                        config.getProxySettings() == ProxySettings.PAC) {
29541a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti                    linkProperties.setHttpProxy(config.getHttpProxy());
29620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                }
29720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
29869b9c6a7d6453c1c76857c5edfeb1d89a1315674Robert Greenwalt                String tcpBufferSizes = mContext.getResources().getString(
29969b9c6a7d6453c1c76857c5edfeb1d89a1315674Robert Greenwalt                        com.android.internal.R.string.config_ethernet_tcp_buffers);
30069b9c6a7d6453c1c76857c5edfeb1d89a1315674Robert Greenwalt                if (TextUtils.isEmpty(tcpBufferSizes) == false) {
30169b9c6a7d6453c1c76857c5edfeb1d89a1315674Robert Greenwalt                    linkProperties.setTcpBufferSizes(tcpBufferSizes);
30269b9c6a7d6453c1c76857c5edfeb1d89a1315674Robert Greenwalt                }
303dcbf3b908024d9ce1d3bf9216f8af11503459afcRobert Greenwalt
30420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                synchronized(EthernetNetworkFactory.this) {
3053191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                    if (mNetworkAgent != null) {
3063191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                        Log.e(TAG, "Already have a NetworkAgent - aborting new request");
3073191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                        return;
3083191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                    }
30920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                    mLinkProperties = linkProperties;
31020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                    mNetworkInfo.setIsAvailable(true);
31120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                    mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr);
3120d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt
3130d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt                    // Create our NetworkAgent.
3140d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt                    mNetworkAgent = new NetworkAgent(mFactory.getLooper(), mContext,
3150d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt                            NETWORK_TYPE, mNetworkInfo, mNetworkCapabilities, mLinkProperties,
3160d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt                            NETWORK_SCORE) {
3170d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt                        public void unwanted() {
3183191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                            synchronized(EthernetNetworkFactory.this) {
3193191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                                if (this == mNetworkAgent) {
3203191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                                    NetworkUtils.stopDhcp(mIface);
3213191f909a20216646f1652537eba6804b5435c74Robert Greenwalt
3223191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                                    mLinkProperties.clear();
3233191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                                    mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null,
3243191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                                            mHwAddr);
3253191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                                    updateAgent();
3263191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                                    mNetworkAgent = null;
3273191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                                    try {
3283191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                                        mNMService.clearInterfaceAddresses(mIface);
3293191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                                    } catch (Exception e) {
3303191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                                        Log.e(TAG, "Failed to clear addresses or disable ipv6" + e);
3313191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                                    }
3323191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                                } else {
3333191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                                    Log.d(TAG, "Ignoring unwanted as we have a more modern " +
3343191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                                            "instance");
3353191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                                }
3363191f909a20216646f1652537eba6804b5435c74Robert Greenwalt                            }
3370d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt                        };
3380d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt                    };
33920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                }
34020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            }
34120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        });
34220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        dhcpThread.start();
34320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    }
34420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
345044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti    /**
34620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti     * Begin monitoring connectivity
34720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti     */
34820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    public synchronized void start(Context context, Handler target) {
34920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        // The services we use.
35020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
35120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        mNMService = INetworkManagementService.Stub.asInterface(b);
35220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        mEthernetManager = (EthernetManager) context.getSystemService(Context.ETHERNET_SERVICE);
35320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
35420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        // Interface match regex.
35520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        mIfaceMatch = context.getResources().getString(
35620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                com.android.internal.R.string.config_ethernet_iface_regex);
35720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
35820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        // Create and register our NetworkFactory.
3590d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt        mFactory = new LocalNetworkFactory(NETWORK_TYPE, context, target.getLooper());
3600d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt        mFactory.setCapabilityFilter(mNetworkCapabilities);
3610d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt        mFactory.setScoreFilter(-1); // this set high when we have an iface
36220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        mFactory.register();
36320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
3640d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt        mContext = context;
3650d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt
36620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        // Start tracking interface change events.
36720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        mInterfaceObserver = new InterfaceObserver();
36820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        try {
36920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            mNMService.registerObserver(mInterfaceObserver);
37020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        } catch (RemoteException e) {
37120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            Log.e(TAG, "Could not register InterfaceObserver " + e);
37220c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        }
37320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
37420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        // If an Ethernet interface is already connected, start tracking that.
37520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        // Otherwise, the first Ethernet interface to appear will be tracked.
37620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        try {
37720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            final String[] ifaces = mNMService.listInterfaces();
37820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            for (String iface : ifaces) {
379044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti                synchronized(this) {
380044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti                    if (maybeTrackInterface(iface)) {
381044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti                        // We have our interface. Track it.
382044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti                        // Note: if the interface already has link (e.g., if we
383044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti                        // crashed and got restarted while it was running),
384044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti                        // we need to fake a link up notification so we start
385044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti                        // configuring it. Since we're already holding the lock,
386044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti                        // any real link up/down notification will only arrive
387044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti                        // after we've done this.
388044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti                        if (mNMService.getInterfaceConfig(iface).hasFlag("running")) {
389044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti                            updateInterfaceState(iface, true);
390044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti                        }
391044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti                        break;
392044a758ebb1e38df875a45e9cfe84f4a53352abaLorenzo Colitti                    }
39320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti                }
39420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            }
39520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        } catch (RemoteException e) {
39620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti            Log.e(TAG, "Could not get list of interfaces " + e);
39720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        }
39820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    }
39920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
40020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    public synchronized void stop() {
40141a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti        NetworkUtils.stopDhcp(mIface);
40241a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti        // ConnectivityService will only forget our NetworkAgent if we send it a NetworkInfo object
40341a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti        // with a state of DISCONNECTED or SUSPENDED. So we can't simply clear our NetworkInfo here:
40441a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti        // that sets the state to IDLE, and ConnectivityService will still think we're connected.
40541a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti        //
40641a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti        // TODO: stop using explicit comparisons to DISCONNECTED / SUSPENDED in ConnectivityService,
40741a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti        // and instead use isConnectedOrConnecting().
40841a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti        mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr);
40941a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti        mLinkUp = false;
41041a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti        updateAgent();
41141a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti        mLinkProperties = new LinkProperties();
41241a372f13a7d19807d91e09f2e955b8a61f02d5cLorenzo Colitti        mNetworkAgent = null;
413a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        setInterfaceInfoLocked("", null);
4140d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt        mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, "");
4150d1b1749dad71372d9baeb0f852d3d91fccac73dRobert Greenwalt        mFactory.unregister();
41620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    }
41720c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti
41820c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    private void initNetworkCapabilities() {
41920c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        mNetworkCapabilities = new NetworkCapabilities();
42020c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET);
4214b1ec3fc8e4e4b432328297c45519fa4f6baa3cdRobert Greenwalt        mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
4224b1ec3fc8e4e4b432328297c45519fa4f6baa3cdRobert Greenwalt        mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
42320c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        // We have no useful data on bandwidth. Say 100M up and 100M down. :-(
42420c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        mNetworkCapabilities.setLinkUpstreamBandwidthKbps(100 * 1000);
42520c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti        mNetworkCapabilities.setLinkDownstreamBandwidthKbps(100 * 1000);
42620c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti    }
427aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti
428a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim    public synchronized boolean isTrackingInterface() {
429a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        return !TextUtils.isEmpty(mIface);
430a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim    }
431a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim
432a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim    /**
433a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim     * Set interface information and notify listeners if availability is changed.
434a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim     * This should be called with the lock held.
435a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim     */
436a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim    private void setInterfaceInfoLocked(String iface, String hwAddr) {
437a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        boolean oldAvailable = isTrackingInterface();
438a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        mIface = iface;
439a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        mHwAddr = hwAddr;
440a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        boolean available = isTrackingInterface();
441a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim
442a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        if (oldAvailable != available) {
443a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim            int n = mListeners.beginBroadcast();
444a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim            for (int i = 0; i < n; i++) {
445a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim                try {
446a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim                    mListeners.getBroadcastItem(i).onAvailabilityChanged(available);
447a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim                } catch (RemoteException e) {
448a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim                    // Do nothing here.
449a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim                }
450a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim            }
451a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim            mListeners.finishBroadcast();
452a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        }
453a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim    }
454a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim
455aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti    synchronized void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
456a3d7e61812f8d68ca109280c4e7589e4f968723aJaewan Kim        if (isTrackingInterface()) {
457aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti            pw.println("Tracking interface: " + mIface);
458aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti            pw.increaseIndent();
459aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti            pw.println("MAC address: " + mHwAddr);
460aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti            pw.println("Link state: " + (mLinkUp ? "up" : "down"));
461aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti            pw.decreaseIndent();
462aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti        } else {
463aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti            pw.println("Not tracking any interface");
464aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti        }
465aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti
466aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti        pw.println();
467aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti        pw.println("NetworkInfo: " + mNetworkInfo);
468aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti        pw.println("LinkProperties: " + mLinkProperties);
469aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti        pw.println("NetworkAgent: " + mNetworkAgent);
470aea43f5901e6591c390b83b10d3dd9b515a6442aLorenzo Colitti    }
47120c1c99c4351abd8bb3d6e8f966fcf3b6de0e5b0Lorenzo Colitti}
472