EthernetNetworkFactory.java revision 69b9c6a7d6453c1c76857c5edfeb1d89a1315674
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2014 The Android Open Source Project
3f1f48bc7f200f54c76b22d845d8ba8419879b375Joseph Wen *
4a06d86ab8177ee9e631e0ee4e39688bf42179bdeLeon Scroggins * Licensed under the Apache License, Version 2.0 (the "License");
57315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III * 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
746cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins *
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.
13f1f48bc7f200f54c76b22d845d8ba8419879b375Joseph Wen * See the License for the specific language governing permissions and
146b849e2123be98eb2a1a25b8abf0b13a279ce952Wei-Ta Chen * limitations under the License.
15a3804cf77f0edd93f6247a055cdafb856b117eecElliott Hughes */
161abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server.ethernet;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopianimport android.content.Context;
20b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopianimport android.net.ConnectivityManager;
21bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craikimport android.net.DhcpResults;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.InterfaceConfiguration;
230102f8a87a7571b1ff537a1293d67ae8fa001167Leon Scroggins IIIimport android.net.NetworkUtils;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.IpConfiguration;
252dcfbefbbeac406d16ec379c6430dd9ee9fd23a1Joseph Wenimport android.net.IpConfiguration.IpAssignment;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.IpConfiguration.ProxySettings;
27f1f48bc7f200f54c76b22d845d8ba8419879b375Joseph Wenimport android.net.LinkAddress;
28f1f48bc7f200f54c76b22d845d8ba8419879b375Joseph Wenimport android.net.LinkProperties;
29f1f48bc7f200f54c76b22d845d8ba8419879b375Joseph Wenimport android.net.NetworkAgent;
301abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craikimport android.net.NetworkCapabilities;
312361098da3b9d9c3eeed410dc72ba62c0e9177cfRomain Guyimport android.net.NetworkFactory;
32f1f48bc7f200f54c76b22d845d8ba8419879b375Joseph Wenimport android.net.NetworkInfo;
33953f9094a2ec14594fa8501d5f3e2d9e300b1b62Wei-Ta Chenimport android.net.NetworkInfo.DetailedState;
34905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craikimport android.net.NetworkRequest;
35905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craikimport android.net.EthernetManager;
36905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craikimport android.net.StaticIpConfiguration;
37905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craikimport android.os.Handler;
38f1f48bc7f200f54c76b22d845d8ba8419879b375Joseph Wenimport android.os.IBinder;
39f1f48bc7f200f54c76b22d845d8ba8419879b375Joseph Wenimport android.os.INetworkManagementService;
40f1f48bc7f200f54c76b22d845d8ba8419879b375Joseph Wenimport android.os.Looper;
41f1f48bc7f200f54c76b22d845d8ba8419879b375Joseph Wenimport android.os.Message;
4237f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haaseimport android.os.Messenger;
4347cd8e921db73e894f94ec4729ade90da50996f5Chris Craikimport android.os.RemoteException;
4437f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haaseimport android.os.ServiceManager;
4547cd8e921db73e894f94ec4729ade90da50996f5Chris Craikimport android.text.TextUtils;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
4747cd8e921db73e894f94ec4729ade90da50996f5Chris Craik
4847cd8e921db73e894f94ec4729ade90da50996f5Chris Craikimport com.android.internal.util.IndentingPrintWriter;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.server.net.BaseNetworkObserver;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.net.Inet4Address;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.concurrent.atomic.AtomicBoolean;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.concurrent.atomic.AtomicInteger;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
58f1f48bc7f200f54c76b22d845d8ba8419879b375Joseph Wen/**
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Manages connectivity for an Ethernet interface.
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Ethernet Interfaces may be present at boot time or appear after boot (e.g.,
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for Ethernet adapters connected over USB). This class currently supports
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * only one interface. When an interface appears on the system (or is present
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * at boot time) this class will start tracking it and bring it up, and will
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * attempt to connect when requested. Any other interfaces that subsequently
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * appear will be ignored until the tracked interface disappears. Only
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * interfaces whose names match the <code>config_ethernet_iface_regex</code>
6895587f9045443f8201d01db1d2bee8ae79edab8cChris Craik * regular expression are tracked.
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This class reports a static network score of 70 when it is tracking an
71a3804cf77f0edd93f6247a055cdafb856b117eecElliott Hughes * interface and that interface's link is up, and a score of 0 otherwise.
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass EthernetNetworkFactory {
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String NETWORK_TYPE = "Ethernet";
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "EthernetNetworkFactory";
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int NETWORK_SCORE = 70;
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final boolean DBG = true;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Tracks interface changes. Called from NetworkManagementService. */
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private InterfaceObserver mInterfaceObserver;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** For static IP configuration */
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private EthernetManager mEthernetManager;
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
872a3d754549abc4b55e6cfc2d0c986d29782b2492Bryan Mawhinney    /** To set link state and configure IP addresses. */
88caf813fe1ec10dda75cd752cb3ff80872ae7ac0bRomain Guy    private INetworkManagementService mNMService;
892a3d754549abc4b55e6cfc2d0c986d29782b2492Bryan Mawhinney
902a3d754549abc4b55e6cfc2d0c986d29782b2492Bryan Mawhinney    /* To communicate with ConnectivityManager */
91bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik    private NetworkCapabilities mNetworkCapabilities;
92bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik    private NetworkAgent mNetworkAgent;
93bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik    private LocalNetworkFactory mFactory;
94bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik    private Context mContext;
95bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik
967b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy    /** Product-dependent regular expression of interface names we track. */
977b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy    private static String mIfaceMatch = "";
987b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy
99bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik    /** Data members. All accesses to these must be synchronized(this). */
100bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik    private static String mIface = "";
101bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik    private String mHwAddr;
102bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik    private static boolean mLinkUp;
103bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik    private NetworkInfo mNetworkInfo;
104bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik    private LinkProperties mLinkProperties;
105bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik
106bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik    EthernetNetworkFactory() {
107bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik        mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, "");
108bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik        mLinkProperties = new LinkProperties();
109bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik        initNetworkCapabilities();
110bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik    }
1117b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy
1127b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy    private class LocalNetworkFactory extends NetworkFactory {
1137b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy        LocalNetworkFactory(String name, Context context, Looper looper) {
1147b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy            super(looper, context, name, new NetworkCapabilities());
115bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik        }
116bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik
117bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik        protected void startNetwork() {
118bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik            onRequestNetwork();
119bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik        }
120bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik        protected void stopNetwork() {
121bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik        }
122bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik    }
123bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik
124bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik
125bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik    /**
12646cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins     * Updates interface state variables.
12746cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins     * Called on link state changes or on startup.
12846cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins     */
12946cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins    private void updateInterfaceState(String iface, boolean up) {
1304a9c3891d4f890109e02bc83fecf9bcdf56a9395Mike Reed        if (!mIface.equals(iface)) {
131905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik            return;
132905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik        }
133905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik        Log.d(TAG, "updateInterface: " + iface + " link " + (up ? "up" : "down"));
13446cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins
135905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik        synchronized(this) {
136905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik            mLinkUp = up;
137905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik            mNetworkInfo.setIsAvailable(up);
138905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik            if (!up) {
139905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik                // Tell the agent we're disconnected. It will call disconnect().
140905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik                mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr);
141905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik            }
142905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik            updateAgent();
143905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik            mFactory.setScoreFilter(up ? NETWORK_SCORE : -1);
144905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik        }
14546cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins    }
14646cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins
147905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik    private class InterfaceObserver extends BaseNetworkObserver {
148905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik        @Override
149905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik        public void interfaceLinkStateChanged(String iface, boolean up) {
150905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik            updateInterfaceState(iface, up);
151905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik        }
152905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik
153905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik        @Override
154905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik        public void interfaceAdded(String iface) {
155905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik            maybeTrackInterface(iface);
156905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik        }
157905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik
158905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik        @Override
159905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik        public void interfaceRemoved(String iface) {
160905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik            stopTrackingInterface(iface);
161905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik        }
1627e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik    }
1637e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik
1647e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik    private void setInterfaceUp(String iface) {
165905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik        // Bring up the interface so we get link status indications.
1667e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik        try {
1677e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik            mNMService.setInterfaceUp(iface);
1687e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik            String hwAddr = null;
1697e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik            InterfaceConfiguration config = mNMService.getInterfaceConfig(iface);
1707e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik
1717e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik            if (config == null) {
1727e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik                Log.e(TAG, "Null iterface config for " + iface + ". Bailing out.");
1737e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik                return;
17446cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins            }
17546cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins
17646cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins            synchronized (this) {
1777e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik                if (mIface.isEmpty()) {
1787e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik                    mIface = iface;
179cd0ba71aa942f35fcdb26808b86f20073b8aff92Chris Craik                    mHwAddr = config.getHardwareAddress();
18046cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins                    mNetworkInfo.setIsAvailable(true);
18146cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins                    mNetworkInfo.setExtraInfo(mHwAddr);
18246cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins                } else {
18346cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins                    Log.e(TAG, "Interface unexpectedly changed from " + iface + " to " + mIface);
18446cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins                    mNMService.setInterfaceDown(iface);
18546cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins                }
18646cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins            }
18746cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins        } catch (RemoteException e) {
18846cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins            Log.e(TAG, "Error upping interface " + mIface + ": " + e);
18946cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins        }
190b644a3b84521e2155a5af985a4d4ed305474e567Derek Sollenberger    }
191b644a3b84521e2155a5af985a4d4ed305474e567Derek Sollenberger
192b644a3b84521e2155a5af985a4d4ed305474e567Derek Sollenberger    private boolean maybeTrackInterface(String iface) {
193cd0ba71aa942f35fcdb26808b86f20073b8aff92Chris Craik        // If we don't already have an interface, and if this interface matches
194b644a3b84521e2155a5af985a4d4ed305474e567Derek Sollenberger        // our regex, start tracking it.
19546cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins        if (!iface.matches(mIfaceMatch) || !mIface.isEmpty())
196cd0ba71aa942f35fcdb26808b86f20073b8aff92Chris Craik            return false;
197cd0ba71aa942f35fcdb26808b86f20073b8aff92Chris Craik
198cd0ba71aa942f35fcdb26808b86f20073b8aff92Chris Craik        Log.d(TAG, "Started tracking interface " + iface);
199cd0ba71aa942f35fcdb26808b86f20073b8aff92Chris Craik        setInterfaceUp(iface);
2007e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik        return true;
2017e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik    }
2027e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik
2037e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik    private void stopTrackingInterface(String iface) {
2047e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik        if (!iface.equals(mIface))
2057e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik            return;
2067e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik
2077e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik        Log.d(TAG, "Stopped tracking interface " + iface);
2087e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik        synchronized (this) {
20947cd8e921db73e894f94ec4729ade90da50996f5Chris Craik            mIface = "";
2107b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy            mHwAddr = null;
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNetworkInfo.setExtraInfo(null);
2127b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy            mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, "");
2130aa39dc2dcfca20f4d9cbeb1699d48a4808f2c70Leon Scroggins III            mLinkProperties = new LinkProperties();
21442a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed            updateAgent();
2157b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy        }
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2172361098da3b9d9c3eeed410dc72ba62c0e9177cfRomain Guy
218905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik    private boolean setStaticIpAddress(StaticIpConfiguration staticConfig) {
219953f9094a2ec14594fa8501d5f3e2d9e300b1b62Wei-Ta Chen        if (staticConfig.ipAddress != null &&
2201abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik                staticConfig.gateway != null &&
2217b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                staticConfig.dnsServers.size() > 0) {
22237f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase            try {
223a3804cf77f0edd93f6247a055cdafb856b117eecElliott Hughes                Log.i(TAG, "Applying static IPv4 configuration to " + mIface + ": " + staticConfig);
2247b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                InterfaceConfiguration config = mNMService.getInterfaceConfig(mIface);
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                config.setLinkAddress(staticConfig.ipAddress);
2262a3d754549abc4b55e6cfc2d0c986d29782b2492Bryan Mawhinney                mNMService.setInterfaceConfig(mIface, config);
2270aa39dc2dcfca20f4d9cbeb1699d48a4808f2c70Leon Scroggins III                return true;
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch(RemoteException|IllegalStateException e) {
2297b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy               Log.e(TAG, "Setting static IP address failed: " + e.getMessage());
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "Invalid static IP configuration.");
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
234a3804cf77f0edd93f6247a055cdafb856b117eecElliott Hughes        return false;
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
23642a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed
2372361098da3b9d9c3eeed410dc72ba62c0e9177cfRomain Guy    public void updateAgent() {
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (EthernetNetworkFactory.this) {
239953f9094a2ec14594fa8501d5f3e2d9e300b1b62Wei-Ta Chen            if (mNetworkAgent == null) return;
240953f9094a2ec14594fa8501d5f3e2d9e300b1b62Wei-Ta Chen            if (DBG) {
2411abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik                Log.i(TAG, "Updating mNetworkAgent with: " +
24237f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase                      mNetworkCapabilities + ", " +
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                      mNetworkInfo + ", " +
244905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik                      mLinkProperties);
245905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik            }
246905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik            mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
247905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik            mNetworkAgent.sendNetworkInfo(mNetworkInfo);
248905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik            mNetworkAgent.sendLinkProperties(mLinkProperties);
249905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik            mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : -1);
250905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik        }
251905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik    }
2527b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy
2537b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy    /* Called by the NetworkFactory on the handler thread. */
254905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik    public void onRequestNetwork() {
255905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik        // TODO: Handle DHCP renew.
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Thread dhcpThread = new Thread(new Runnable() {
2577b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy            public void run() {
258c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed                if (DBG) Log.i(TAG, "dhcpThread(+" + mIface + "): mNetworkInfo=" + mNetworkInfo);
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                LinkProperties linkProperties;
260a3804cf77f0edd93f6247a055cdafb856b117eecElliott Hughes
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                IpConfiguration config = mEthernetManager.getConfiguration();
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
263953f9094a2ec14594fa8501d5f3e2d9e300b1b62Wei-Ta Chen                if (config.getIpAssignment() == IpAssignment.STATIC) {
2641abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik                    if (!setStaticIpAddress(config.getStaticIpConfiguration())) {
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // We've already logged an error.
2667e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik                        return;
2679f58361e98be7386a4eadd3aa254e9b7d09d0a3bChris Craik                    }
2687e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik                    linkProperties = config.getStaticIpConfiguration().toLinkProperties(mIface);
26936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat                } else {
2707e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik                    mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr);
2712a6ecae93d4effa47827029d74f2136b5ae8558dDerek Sollenberger
2727e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik                    DhcpResults dhcpResults = new DhcpResults();
2737e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik                    // TODO: Handle DHCP renewals better.
2747e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik                    // In general runDhcp handles DHCP renewals for us, because
2757e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik                    // the dhcp client stays running, but if the renewal fails,
2762a6ecae93d4effa47827029d74f2136b5ae8558dDerek Sollenberger                    // we will lose our IP address and connectivity without
27737f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase                    // noticing.
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!NetworkUtils.runDhcp(mIface, dhcpResults)) {
2797e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik                        Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
2807e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik                        mFactory.setScoreFilter(-1);
2817e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik                        return;
2827e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik                    }
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    linkProperties = dhcpResults.toLinkProperties(mIface);
284c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed                }
285905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik                if (config.getProxySettings() == ProxySettings.STATIC ||
286905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik                        config.getProxySettings() == ProxySettings.PAC) {
287905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik                    linkProperties.setHttpProxy(config.getHttpProxy());
288905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik                }
289905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik
290905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik                String tcpBufferSizes = mContext.getResources().getString(
291905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik                        com.android.internal.R.string.config_ethernet_tcp_buffers);
2921ffe727c0616ca11092a45c3dfb94479fe55fdd9Leon Scroggins III                if (TextUtils.isEmpty(tcpBufferSizes) == false) {
2931ffe727c0616ca11092a45c3dfb94479fe55fdd9Leon Scroggins III                    linkProperties.setTcpBufferSizes(tcpBufferSizes);
2941ffe727c0616ca11092a45c3dfb94479fe55fdd9Leon Scroggins III                }
295905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik
296905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik                synchronized(EthernetNetworkFactory.this) {
297905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik                    if (mNetworkAgent != null) {
298905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik                        Log.e(TAG, "Already have a NetworkAgent - aborting new request");
299905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik                        return;
300905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik                    }
301905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik                    mLinkProperties = linkProperties;
302905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik                    mNetworkInfo.setIsAvailable(true);
3036b0437c2c7a552c8195956444facff3532e25c21Derek Sollenberger                    mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr);
3046b0437c2c7a552c8195956444facff3532e25c21Derek Sollenberger
3056b0437c2c7a552c8195956444facff3532e25c21Derek Sollenberger                    // Create our NetworkAgent.
3066b0437c2c7a552c8195956444facff3532e25c21Derek Sollenberger                    mNetworkAgent = new NetworkAgent(mFactory.getLooper(), mContext,
3076b0437c2c7a552c8195956444facff3532e25c21Derek Sollenberger                            NETWORK_TYPE, mNetworkInfo, mNetworkCapabilities, mLinkProperties,
3086b0437c2c7a552c8195956444facff3532e25c21Derek Sollenberger                            NETWORK_SCORE) {
3096b0437c2c7a552c8195956444facff3532e25c21Derek Sollenberger                        public void unwanted() {
3106b0437c2c7a552c8195956444facff3532e25c21Derek Sollenberger                            synchronized(EthernetNetworkFactory.this) {
3116b0437c2c7a552c8195956444facff3532e25c21Derek Sollenberger                                if (this == mNetworkAgent) {
3126b0437c2c7a552c8195956444facff3532e25c21Derek Sollenberger                                    NetworkUtils.stopDhcp(mIface);
3136b0437c2c7a552c8195956444facff3532e25c21Derek Sollenberger
3146b0437c2c7a552c8195956444facff3532e25c21Derek Sollenberger                                    mLinkProperties.clear();
3156b0437c2c7a552c8195956444facff3532e25c21Derek Sollenberger                                    mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null,
3166b0437c2c7a552c8195956444facff3532e25c21Derek Sollenberger                                            mHwAddr);
3177e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik                                    updateAgent();
31842a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed                                    mNetworkAgent = null;
319c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed                                    try {
320c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed                                        mNMService.clearInterfaceAddresses(mIface);
321c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed                                    } catch (Exception e) {
3227e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik                                        Log.e(TAG, "Failed to clear addresses or disable ipv6" + e);
3237e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik                                    }
3247b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                                } else {
3250aa39dc2dcfca20f4d9cbeb1699d48a4808f2c70Leon Scroggins III                                    Log.d(TAG, "Ignoring unwanted as we have a more modern " +
3267b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                                            "instance");
3277b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                                }
3287b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                            }
3297b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                        };
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    };
3317b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                }
3327b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy            }
3337b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy        });
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dhcpThread.start();
3357b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy    }
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
337c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed    /**
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Begin monitoring connectivity
3390aa39dc2dcfca20f4d9cbeb1699d48a4808f2c70Leon Scroggins III     */
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized void start(Context context, Handler target) {
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // The services we use.
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNMService = INetworkManagementService.Stub.asInterface(b);
34447cd8e921db73e894f94ec4729ade90da50996f5Chris Craik        mEthernetManager = (EthernetManager) context.getSystemService(Context.ETHERNET_SERVICE);
3457b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy
346bd8db2e87e16900ff9b87937d3ccff6a50bd5b2aChris Craik        // Interface match regex.
3477b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy        mIfaceMatch = context.getResources().getString(
3487b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                com.android.internal.R.string.config_ethernet_iface_regex);
34947cd8e921db73e894f94ec4729ade90da50996f5Chris Craik
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Create and register our NetworkFactory.
3517b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy        mFactory = new LocalNetworkFactory(NETWORK_TYPE, context, target.getLooper());
352c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed        mFactory.setCapabilityFilter(mNetworkCapabilities);
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFactory.setScoreFilter(-1); // this set high when we have an iface
3547b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy        mFactory.register();
3557b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy
3567b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy        mContext = context;
357c70e06bbfac0d92ec218a32e35d9d7fa80f23cc9Mike Reed
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Start tracking interface change events.
3597b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy        mInterfaceObserver = new InterfaceObserver();
36047cd8e921db73e894f94ec4729ade90da50996f5Chris Craik        try {
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNMService.registerObserver(mInterfaceObserver);
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "Could not register InterfaceObserver " + e);
36447cd8e921db73e894f94ec4729ade90da50996f5Chris Craik        }
36547cd8e921db73e894f94ec4729ade90da50996f5Chris Craik
36647cd8e921db73e894f94ec4729ade90da50996f5Chris Craik        // If an Ethernet interface is already connected, start tracking that.
36747cd8e921db73e894f94ec4729ade90da50996f5Chris Craik        // Otherwise, the first Ethernet interface to appear will be tracked.
36847cd8e921db73e894f94ec4729ade90da50996f5Chris Craik        try {
36977b5cad3efedd20f2b7cc14d87ccce1b0261960aChris Craik            final String[] ifaces = mNMService.listInterfaces();
370a08d10fa7051668b629d561bb8411e34d28fdabfMathieu Chartier            for (String iface : ifaces) {
371a08d10fa7051668b629d561bb8411e34d28fdabfMathieu Chartier                synchronized(this) {
372a08d10fa7051668b629d561bb8411e34d28fdabfMathieu Chartier                    if (maybeTrackInterface(iface)) {
373ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani                        // We have our interface. Track it.
37447cd8e921db73e894f94ec4729ade90da50996f5Chris Craik                        // Note: if the interface already has link (e.g., if we
375ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani                        // crashed and got restarted while it was running),
376ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani                        // we need to fake a link up notification so we start
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // configuring it. Since we're already holding the lock,
3787b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                        // any real link up/down notification will only arrive
3797b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                        // after we've done this.
3807b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                        if (mNMService.getInterfaceConfig(iface).hasFlag("running")) {
3817b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                            updateInterfaceState(iface, true);
3827b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                        }
3837b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy                        break;
3847e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik                    }
3857e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik                }
3867b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy            }
387905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik        } catch (RemoteException e) {
38846cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins            Log.e(TAG, "Could not get list of interfaces " + e);
3898790be6de3644e332ec6a17c855da89ffc13a9bfLeon Scroggins III        }
3908790be6de3644e332ec6a17c855da89ffc13a9bfLeon Scroggins III    }
3918790be6de3644e332ec6a17c855da89ffc13a9bfLeon Scroggins III
392b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    public synchronized void stop() {
39346cb9bdbf56b27cbf2ab878b41d21e30896a4feaLeon Scroggins        NetworkUtils.stopDhcp(mIface);
394905e8246ef0bd20ee28d81ce3da0c5e5fc8e3913Chris Craik        // ConnectivityService will only forget our NetworkAgent if we send it a NetworkInfo object
395005bfc694d167b7da4b565a1c4de03592fdbe86eRaph Levien        // with a state of DISCONNECTED or SUSPENDED. So we can't simply clear our NetworkInfo here:
396005bfc694d167b7da4b565a1c4de03592fdbe86eRaph Levien        // that sets the state to IDLE, and ConnectivityService will still think we're connected.
3971ffe727c0616ca11092a45c3dfb94479fe55fdd9Leon Scroggins III        //
3981ffe727c0616ca11092a45c3dfb94479fe55fdd9Leon Scroggins III        // TODO: stop using explicit comparisons to DISCONNECTED / SUSPENDED in ConnectivityService,
3991ffe727c0616ca11092a45c3dfb94479fe55fdd9Leon Scroggins III        // and instead use isConnectedOrConnecting().
4001ffe727c0616ca11092a45c3dfb94479fe55fdd9Leon Scroggins III        mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr);
4011ffe727c0616ca11092a45c3dfb94479fe55fdd9Leon Scroggins III        mLinkUp = false;
4021ffe727c0616ca11092a45c3dfb94479fe55fdd9Leon Scroggins III        updateAgent();
4037b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy        mLinkProperties = new LinkProperties();
4047b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy        mNetworkAgent = null;
405b644a3b84521e2155a5af985a4d4ed305474e567Derek Sollenberger        mIface = "";
4067b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy        mHwAddr = null;
4077e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik        mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, "");
4087b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy        mFactory.unregister();
4097e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik    }
4107e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik
4117e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik    private void initNetworkCapabilities() {
4127b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy        mNetworkCapabilities = new NetworkCapabilities();
4137b2f8b8fb7064a1d3b6d942b978c30c24c9d7299Romain Guy        mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET);
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
41547cd8e921db73e894f94ec4729ade90da50996f5Chris Craik        mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // We have no useful data on bandwidth. Say 100M up and 100M down. :-(
41747cd8e921db73e894f94ec4729ade90da50996f5Chris Craik        mNetworkCapabilities.setLinkUpstreamBandwidthKbps(100 * 1000);
41847cd8e921db73e894f94ec4729ade90da50996f5Chris Craik        mNetworkCapabilities.setLinkDownstreamBandwidthKbps(100 * 1000);
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    synchronized void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!TextUtils.isEmpty(mIface)) {
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("Tracking interface: " + mIface);
4240aa39dc2dcfca20f4d9cbeb1699d48a4808f2c70Leon Scroggins III            pw.increaseIndent();
4250aa39dc2dcfca20f4d9cbeb1699d48a4808f2c70Leon Scroggins III            pw.println("MAC address: " + mHwAddr);
4260aa39dc2dcfca20f4d9cbeb1699d48a4808f2c70Leon Scroggins III            pw.println("Link state: " + (mLinkUp ? "up" : "down"));
427b2fe3be4fffc9ff1bfbba0c450d64ccd6e6c4011Marco Nelissen            pw.decreaseIndent();
428b2fe3be4fffc9ff1bfbba0c450d64ccd6e6c4011Marco Nelissen        } else {
4292361098da3b9d9c3eeed410dc72ba62c0e9177cfRomain Guy            pw.println("Not tracking any interface");
4307e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik        }
4312361098da3b9d9c3eeed410dc72ba62c0e9177cfRomain Guy
4320aa39dc2dcfca20f4d9cbeb1699d48a4808f2c70Leon Scroggins III        pw.println();
4332361098da3b9d9c3eeed410dc72ba62c0e9177cfRomain Guy        pw.println("NetworkInfo: " + mNetworkInfo);
43437f74cad46c6f1799aec3c52e8f47598237f43d4Chet Haase        pw.println("LinkProperties: " + mLinkProperties);
43527d83834143c117cbc0d06147c4374553f26b683Jeff Brown        pw.println("NetworkAgent: " + mNetworkAgent);
43627d83834143c117cbc0d06147c4374553f26b683Jeff Brown    }
43727d83834143c117cbc0d06147c4374553f26b683Jeff Brown}
4387e8c03c0fed64c73a4f0cfb96a2c6905b348a143Chris Craik