blob: 6074dda6e0f1be2be33bc2dcf481e53e7d30e391 [file] [log] [blame]
Lorenzo Colitti20c1c992014-05-20 16:58:34 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.ethernet;
18
19import android.content.Context;
20import android.net.ConnectivityManager;
Lorenzo Colitti20c1c992014-05-20 16:58:34 -070021import android.net.DhcpResults;
Jaewan Kima3d7e612014-10-20 12:03:46 +090022import android.net.EthernetManager;
23import android.net.IEthernetServiceListener;
Lorenzo Colitti20c1c992014-05-20 16:58:34 -070024import android.net.InterfaceConfiguration;
Lorenzo Colitti20c1c992014-05-20 16:58:34 -070025import android.net.IpConfiguration;
26import android.net.IpConfiguration.IpAssignment;
27import android.net.IpConfiguration.ProxySettings;
Lorenzo Colitti20c1c992014-05-20 16:58:34 -070028import android.net.LinkProperties;
29import android.net.NetworkAgent;
30import android.net.NetworkCapabilities;
Robert Greenwalt0d1b1742014-05-27 17:59:24 -070031import android.net.NetworkFactory;
Lorenzo Colitti20c1c992014-05-20 16:58:34 -070032import android.net.NetworkInfo;
33import android.net.NetworkInfo.DetailedState;
Jaewan Kima3d7e612014-10-20 12:03:46 +090034import android.net.NetworkUtils;
Lorenzo Colitti41a372f2014-08-12 10:49:39 +090035import android.net.StaticIpConfiguration;
Lorenzo Colitti20c1c992014-05-20 16:58:34 -070036import android.os.Handler;
37import android.os.IBinder;
38import android.os.INetworkManagementService;
39import android.os.Looper;
Jaewan Kima3d7e612014-10-20 12:03:46 +090040import android.os.RemoteCallbackList;
Lorenzo Colitti20c1c992014-05-20 16:58:34 -070041import android.os.RemoteException;
42import android.os.ServiceManager;
43import android.text.TextUtils;
44import android.util.Log;
45
Lorenzo Colittiaea43f52014-08-19 11:45:46 -070046import com.android.internal.util.IndentingPrintWriter;
Lorenzo Colitti20c1c992014-05-20 16:58:34 -070047import com.android.server.net.BaseNetworkObserver;
48
Lorenzo Colittiaea43f52014-08-19 11:45:46 -070049import java.io.FileDescriptor;
50import java.io.PrintWriter;
Lorenzo Colitti20c1c992014-05-20 16:58:34 -070051
52
Lorenzo Colitti20c1c992014-05-20 16:58:34 -070053/**
Lorenzo Colitti044a7582014-05-22 12:26:37 -070054 * Manages connectivity for an Ethernet interface.
55 *
56 * Ethernet Interfaces may be present at boot time or appear after boot (e.g.,
57 * for Ethernet adapters connected over USB). This class currently supports
58 * only one interface. When an interface appears on the system (or is present
59 * at boot time) this class will start tracking it and bring it up, and will
60 * attempt to connect when requested. Any other interfaces that subsequently
61 * appear will be ignored until the tracked interface disappears. Only
62 * interfaces whose names match the <code>config_ethernet_iface_regex</code>
63 * regular expression are tracked.
64 *
65 * This class reports a static network score of 70 when it is tracking an
66 * interface and that interface's link is up, and a score of 0 otherwise.
67 *
Lorenzo Colitti20c1c992014-05-20 16:58:34 -070068 * @hide
69 */
Robert Greenwalt0d1b1742014-05-27 17:59:24 -070070class EthernetNetworkFactory {
71 private static final String NETWORK_TYPE = "Ethernet";
Lorenzo Colitti20c1c992014-05-20 16:58:34 -070072 private static final String TAG = "EthernetNetworkFactory";
73 private static final int NETWORK_SCORE = 70;
74 private static final boolean DBG = true;
75
Lorenzo Colitti044a7582014-05-22 12:26:37 -070076 /** Tracks interface changes. Called from NetworkManagementService. */
Lorenzo Colitti20c1c992014-05-20 16:58:34 -070077 private InterfaceObserver mInterfaceObserver;
78
79 /** For static IP configuration */
80 private EthernetManager mEthernetManager;
81
82 /** To set link state and configure IP addresses. */
83 private INetworkManagementService mNMService;
84
85 /* To communicate with ConnectivityManager */
86 private NetworkCapabilities mNetworkCapabilities;
87 private NetworkAgent mNetworkAgent;
Robert Greenwalt0d1b1742014-05-27 17:59:24 -070088 private LocalNetworkFactory mFactory;
89 private Context mContext;
Lorenzo Colitti20c1c992014-05-20 16:58:34 -070090
Lorenzo Colitti044a7582014-05-22 12:26:37 -070091 /** Product-dependent regular expression of interface names we track. */
Lorenzo Colitti20c1c992014-05-20 16:58:34 -070092 private static String mIfaceMatch = "";
93
Jaewan Kima3d7e612014-10-20 12:03:46 +090094 /** To notify Ethernet status. */
95 private final RemoteCallbackList<IEthernetServiceListener> mListeners;
96
Lorenzo Colitti044a7582014-05-22 12:26:37 -070097 /** Data members. All accesses to these must be synchronized(this). */
Lorenzo Colitti20c1c992014-05-20 16:58:34 -070098 private static String mIface = "";
99 private String mHwAddr;
100 private static boolean mLinkUp;
101 private NetworkInfo mNetworkInfo;
102 private LinkProperties mLinkProperties;
103
Jaewan Kima3d7e612014-10-20 12:03:46 +0900104 EthernetNetworkFactory(RemoteCallbackList<IEthernetServiceListener> listeners) {
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700105 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, "");
106 mLinkProperties = new LinkProperties();
107 initNetworkCapabilities();
Jaewan Kima3d7e612014-10-20 12:03:46 +0900108 mListeners = listeners;
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700109 }
110
Robert Greenwalt0d1b1742014-05-27 17:59:24 -0700111 private class LocalNetworkFactory extends NetworkFactory {
112 LocalNetworkFactory(String name, Context context, Looper looper) {
113 super(looper, context, name, new NetworkCapabilities());
114 }
115
116 protected void startNetwork() {
117 onRequestNetwork();
118 }
119 protected void stopNetwork() {
Robert Greenwalt0d1b1742014-05-27 17:59:24 -0700120 }
121 }
122
123
Lorenzo Colitti044a7582014-05-22 12:26:37 -0700124 /**
125 * Updates interface state variables.
126 * Called on link state changes or on startup.
127 */
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700128 private void updateInterfaceState(String iface, boolean up) {
129 if (!mIface.equals(iface)) {
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700130 return;
131 }
132 Log.d(TAG, "updateInterface: " + iface + " link " + (up ? "up" : "down"));
133
134 synchronized(this) {
135 mLinkUp = up;
136 mNetworkInfo.setIsAvailable(up);
Lorenzo Colitti044a7582014-05-22 12:26:37 -0700137 if (!up) {
138 // Tell the agent we're disconnected. It will call disconnect().
139 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr);
140 }
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700141 updateAgent();
Robert Greenwalte3cbf2e2014-09-10 10:06:32 -0700142 // set our score lower than any network could go
143 // so we get dropped. TODO - just unregister the factory
144 // when link goes down.
Robert Greenwalt0d1b1742014-05-27 17:59:24 -0700145 mFactory.setScoreFilter(up ? NETWORK_SCORE : -1);
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700146 }
147 }
148
149 private class InterfaceObserver extends BaseNetworkObserver {
150 @Override
151 public void interfaceLinkStateChanged(String iface, boolean up) {
152 updateInterfaceState(iface, up);
153 }
154
155 @Override
156 public void interfaceAdded(String iface) {
157 maybeTrackInterface(iface);
158 }
159
160 @Override
161 public void interfaceRemoved(String iface) {
162 stopTrackingInterface(iface);
163 }
164 }
165
166 private void setInterfaceUp(String iface) {
167 // Bring up the interface so we get link status indications.
168 try {
Pierre Couillaudef8e0b92015-02-11 08:55:29 -0800169 NetworkUtils.stopDhcp(iface);
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700170 mNMService.setInterfaceUp(iface);
171 String hwAddr = null;
172 InterfaceConfiguration config = mNMService.getInterfaceConfig(iface);
173
174 if (config == null) {
175 Log.e(TAG, "Null iterface config for " + iface + ". Bailing out.");
176 return;
177 }
178
179 synchronized (this) {
Jaewan Kima3d7e612014-10-20 12:03:46 +0900180 if (!isTrackingInterface()) {
181 setInterfaceInfoLocked(iface, config.getHardwareAddress());
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700182 mNetworkInfo.setIsAvailable(true);
183 mNetworkInfo.setExtraInfo(mHwAddr);
184 } else {
185 Log.e(TAG, "Interface unexpectedly changed from " + iface + " to " + mIface);
186 mNMService.setInterfaceDown(iface);
187 }
188 }
189 } catch (RemoteException e) {
190 Log.e(TAG, "Error upping interface " + mIface + ": " + e);
191 }
192 }
193
194 private boolean maybeTrackInterface(String iface) {
195 // If we don't already have an interface, and if this interface matches
196 // our regex, start tracking it.
Jaewan Kima3d7e612014-10-20 12:03:46 +0900197 if (!iface.matches(mIfaceMatch) || isTrackingInterface())
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700198 return false;
199
200 Log.d(TAG, "Started tracking interface " + iface);
201 setInterfaceUp(iface);
202 return true;
203 }
204
205 private void stopTrackingInterface(String iface) {
206 if (!iface.equals(mIface))
207 return;
208
209 Log.d(TAG, "Stopped tracking interface " + iface);
Lorenzo Colitti74d270d2014-10-01 13:52:40 +0900210 // TODO: Unify this codepath with stop().
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700211 synchronized (this) {
Lorenzo Colitti74d270d2014-10-01 13:52:40 +0900212 NetworkUtils.stopDhcp(mIface);
Jaewan Kima3d7e612014-10-20 12:03:46 +0900213 setInterfaceInfoLocked("", null);
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700214 mNetworkInfo.setExtraInfo(null);
Lorenzo Colitti74d270d2014-10-01 13:52:40 +0900215 mLinkUp = false;
216 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr);
217 updateAgent();
218 mNetworkAgent = null;
Lorenzo Colitti044a7582014-05-22 12:26:37 -0700219 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, "");
220 mLinkProperties = new LinkProperties();
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700221 }
222 }
223
Lorenzo Colitti41a372f2014-08-12 10:49:39 +0900224 private boolean setStaticIpAddress(StaticIpConfiguration staticConfig) {
225 if (staticConfig.ipAddress != null &&
226 staticConfig.gateway != null &&
227 staticConfig.dnsServers.size() > 0) {
228 try {
229 Log.i(TAG, "Applying static IPv4 configuration to " + mIface + ": " + staticConfig);
230 InterfaceConfiguration config = mNMService.getInterfaceConfig(mIface);
231 config.setLinkAddress(staticConfig.ipAddress);
232 mNMService.setInterfaceConfig(mIface, config);
233 return true;
234 } catch(RemoteException|IllegalStateException e) {
235 Log.e(TAG, "Setting static IP address failed: " + e.getMessage());
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700236 }
Lorenzo Colitti41a372f2014-08-12 10:49:39 +0900237 } else {
238 Log.e(TAG, "Invalid static IP configuration.");
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700239 }
Lorenzo Colitti41a372f2014-08-12 10:49:39 +0900240 return false;
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700241 }
242
Robert Greenwalt0d1b1742014-05-27 17:59:24 -0700243 public void updateAgent() {
244 synchronized (EthernetNetworkFactory.this) {
245 if (mNetworkAgent == null) return;
246 if (DBG) {
247 Log.i(TAG, "Updating mNetworkAgent with: " +
248 mNetworkCapabilities + ", " +
249 mNetworkInfo + ", " +
250 mLinkProperties);
251 }
252 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
253 mNetworkAgent.sendNetworkInfo(mNetworkInfo);
254 mNetworkAgent.sendLinkProperties(mLinkProperties);
Robert Greenwalte3cbf2e2014-09-10 10:06:32 -0700255 // never set the network score below 0.
256 mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : 0);
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700257 }
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700258 }
259
Robert Greenwalt0d1b1742014-05-27 17:59:24 -0700260 /* Called by the NetworkFactory on the handler thread. */
261 public void onRequestNetwork() {
262 // TODO: Handle DHCP renew.
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700263 Thread dhcpThread = new Thread(new Runnable() {
264 public void run() {
Lorenzo Colitti0e47a8a2015-08-04 13:27:28 +0900265 if (DBG) Log.i(TAG, "dhcpThread(" + mIface + "): mNetworkInfo=" + mNetworkInfo);
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700266 LinkProperties linkProperties;
267
268 IpConfiguration config = mEthernetManager.getConfiguration();
269
Lorenzo Colitti41a372f2014-08-12 10:49:39 +0900270 if (config.getIpAssignment() == IpAssignment.STATIC) {
271 if (!setStaticIpAddress(config.getStaticIpConfiguration())) {
272 // We've already logged an error.
273 return;
274 }
275 linkProperties = config.getStaticIpConfiguration().toLinkProperties(mIface);
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700276 } else {
Robert Greenwalt0d1b1742014-05-27 17:59:24 -0700277 mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr);
Robert Greenwalt0d1b1742014-05-27 17:59:24 -0700278
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700279 DhcpResults dhcpResults = new DhcpResults();
Lorenzo Colitti044a7582014-05-22 12:26:37 -0700280 // TODO: Handle DHCP renewals better.
281 // In general runDhcp handles DHCP renewals for us, because
282 // the dhcp client stays running, but if the renewal fails,
283 // we will lose our IP address and connectivity without
284 // noticing.
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700285 if (!NetworkUtils.runDhcp(mIface, dhcpResults)) {
286 Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
Robert Greenwalte3cbf2e2014-09-10 10:06:32 -0700287 // set our score lower than any network could go
288 // so we get dropped.
Robert Greenwalt0d1b1742014-05-27 17:59:24 -0700289 mFactory.setScoreFilter(-1);
Lorenzo Colitti0e47a8a2015-08-04 13:27:28 +0900290 // If DHCP timed out (as opposed to failing), the DHCP client will still be
291 // running, because in M we changed its timeout to infinite. Stop it now.
292 NetworkUtils.stopDhcp(mIface);
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700293 return;
294 }
Lorenzo Colitti41a372f2014-08-12 10:49:39 +0900295 linkProperties = dhcpResults.toLinkProperties(mIface);
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700296 }
Lorenzo Colitti41a372f2014-08-12 10:49:39 +0900297 if (config.getProxySettings() == ProxySettings.STATIC ||
298 config.getProxySettings() == ProxySettings.PAC) {
299 linkProperties.setHttpProxy(config.getHttpProxy());
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700300 }
301
Robert Greenwalt69b9c6a2014-08-21 16:28:18 -0700302 String tcpBufferSizes = mContext.getResources().getString(
303 com.android.internal.R.string.config_ethernet_tcp_buffers);
304 if (TextUtils.isEmpty(tcpBufferSizes) == false) {
305 linkProperties.setTcpBufferSizes(tcpBufferSizes);
306 }
Robert Greenwaltdcbf3b92014-08-06 22:27:17 -0700307
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700308 synchronized(EthernetNetworkFactory.this) {
Robert Greenwalt3191f902014-06-19 16:26:03 -0700309 if (mNetworkAgent != null) {
310 Log.e(TAG, "Already have a NetworkAgent - aborting new request");
311 return;
312 }
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700313 mLinkProperties = linkProperties;
314 mNetworkInfo.setIsAvailable(true);
315 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr);
Robert Greenwalt0d1b1742014-05-27 17:59:24 -0700316
317 // Create our NetworkAgent.
318 mNetworkAgent = new NetworkAgent(mFactory.getLooper(), mContext,
319 NETWORK_TYPE, mNetworkInfo, mNetworkCapabilities, mLinkProperties,
320 NETWORK_SCORE) {
321 public void unwanted() {
Robert Greenwalt3191f902014-06-19 16:26:03 -0700322 synchronized(EthernetNetworkFactory.this) {
323 if (this == mNetworkAgent) {
324 NetworkUtils.stopDhcp(mIface);
325
326 mLinkProperties.clear();
327 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null,
328 mHwAddr);
329 updateAgent();
330 mNetworkAgent = null;
331 try {
332 mNMService.clearInterfaceAddresses(mIface);
333 } catch (Exception e) {
334 Log.e(TAG, "Failed to clear addresses or disable ipv6" + e);
335 }
336 } else {
337 Log.d(TAG, "Ignoring unwanted as we have a more modern " +
338 "instance");
339 }
340 }
Robert Greenwalt0d1b1742014-05-27 17:59:24 -0700341 };
342 };
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700343 }
344 }
345 });
346 dhcpThread.start();
347 }
348
Lorenzo Colitti044a7582014-05-22 12:26:37 -0700349 /**
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700350 * Begin monitoring connectivity
351 */
352 public synchronized void start(Context context, Handler target) {
353 // The services we use.
354 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
355 mNMService = INetworkManagementService.Stub.asInterface(b);
356 mEthernetManager = (EthernetManager) context.getSystemService(Context.ETHERNET_SERVICE);
357
358 // Interface match regex.
359 mIfaceMatch = context.getResources().getString(
360 com.android.internal.R.string.config_ethernet_iface_regex);
361
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700362 // Create and register our NetworkFactory.
Robert Greenwalt0d1b1742014-05-27 17:59:24 -0700363 mFactory = new LocalNetworkFactory(NETWORK_TYPE, context, target.getLooper());
364 mFactory.setCapabilityFilter(mNetworkCapabilities);
365 mFactory.setScoreFilter(-1); // this set high when we have an iface
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700366 mFactory.register();
367
Robert Greenwalt0d1b1742014-05-27 17:59:24 -0700368 mContext = context;
369
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700370 // Start tracking interface change events.
371 mInterfaceObserver = new InterfaceObserver();
372 try {
373 mNMService.registerObserver(mInterfaceObserver);
374 } catch (RemoteException e) {
375 Log.e(TAG, "Could not register InterfaceObserver " + e);
376 }
377
378 // If an Ethernet interface is already connected, start tracking that.
379 // Otherwise, the first Ethernet interface to appear will be tracked.
380 try {
381 final String[] ifaces = mNMService.listInterfaces();
382 for (String iface : ifaces) {
Lorenzo Colitti044a7582014-05-22 12:26:37 -0700383 synchronized(this) {
384 if (maybeTrackInterface(iface)) {
385 // We have our interface. Track it.
386 // Note: if the interface already has link (e.g., if we
387 // crashed and got restarted while it was running),
388 // we need to fake a link up notification so we start
389 // configuring it. Since we're already holding the lock,
390 // any real link up/down notification will only arrive
391 // after we've done this.
392 if (mNMService.getInterfaceConfig(iface).hasFlag("running")) {
393 updateInterfaceState(iface, true);
394 }
395 break;
396 }
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700397 }
398 }
Lorenzo Colitti9fc9da22015-09-08 16:21:52 +0900399 } catch (RemoteException|IllegalStateException e) {
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700400 Log.e(TAG, "Could not get list of interfaces " + e);
401 }
402 }
403
404 public synchronized void stop() {
Lorenzo Colitti41a372f2014-08-12 10:49:39 +0900405 NetworkUtils.stopDhcp(mIface);
406 // ConnectivityService will only forget our NetworkAgent if we send it a NetworkInfo object
407 // with a state of DISCONNECTED or SUSPENDED. So we can't simply clear our NetworkInfo here:
408 // that sets the state to IDLE, and ConnectivityService will still think we're connected.
409 //
410 // TODO: stop using explicit comparisons to DISCONNECTED / SUSPENDED in ConnectivityService,
411 // and instead use isConnectedOrConnecting().
412 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr);
413 mLinkUp = false;
414 updateAgent();
415 mLinkProperties = new LinkProperties();
416 mNetworkAgent = null;
Jaewan Kima3d7e612014-10-20 12:03:46 +0900417 setInterfaceInfoLocked("", null);
Robert Greenwalt0d1b1742014-05-27 17:59:24 -0700418 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, "");
Robert Greenwalt0d1b1742014-05-27 17:59:24 -0700419 mFactory.unregister();
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700420 }
421
422 private void initNetworkCapabilities() {
423 mNetworkCapabilities = new NetworkCapabilities();
424 mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET);
Robert Greenwalt4b1ec3f2014-06-09 17:36:54 -0700425 mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
426 mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700427 // We have no useful data on bandwidth. Say 100M up and 100M down. :-(
428 mNetworkCapabilities.setLinkUpstreamBandwidthKbps(100 * 1000);
429 mNetworkCapabilities.setLinkDownstreamBandwidthKbps(100 * 1000);
430 }
Lorenzo Colittiaea43f52014-08-19 11:45:46 -0700431
Jaewan Kima3d7e612014-10-20 12:03:46 +0900432 public synchronized boolean isTrackingInterface() {
433 return !TextUtils.isEmpty(mIface);
434 }
435
436 /**
437 * Set interface information and notify listeners if availability is changed.
438 * This should be called with the lock held.
439 */
440 private void setInterfaceInfoLocked(String iface, String hwAddr) {
441 boolean oldAvailable = isTrackingInterface();
442 mIface = iface;
443 mHwAddr = hwAddr;
444 boolean available = isTrackingInterface();
445
446 if (oldAvailable != available) {
447 int n = mListeners.beginBroadcast();
448 for (int i = 0; i < n; i++) {
449 try {
450 mListeners.getBroadcastItem(i).onAvailabilityChanged(available);
451 } catch (RemoteException e) {
452 // Do nothing here.
453 }
454 }
455 mListeners.finishBroadcast();
456 }
457 }
458
Lorenzo Colittiaea43f52014-08-19 11:45:46 -0700459 synchronized void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
Jaewan Kima3d7e612014-10-20 12:03:46 +0900460 if (isTrackingInterface()) {
Lorenzo Colittiaea43f52014-08-19 11:45:46 -0700461 pw.println("Tracking interface: " + mIface);
462 pw.increaseIndent();
463 pw.println("MAC address: " + mHwAddr);
464 pw.println("Link state: " + (mLinkUp ? "up" : "down"));
465 pw.decreaseIndent();
466 } else {
467 pw.println("Not tracking any interface");
468 }
469
470 pw.println();
471 pw.println("NetworkInfo: " + mNetworkInfo);
472 pw.println("LinkProperties: " + mLinkProperties);
473 pw.println("NetworkAgent: " + mNetworkAgent);
474 }
Lorenzo Colitti20c1c992014-05-20 16:58:34 -0700475}