Make Ethernet more robust. am: 9effed6f9e
am: 00f803738d
Change-Id: I03f9b28561e0fb1fd1c5e388820e02748c8580b3
This commit is contained in:
@@ -34,7 +34,6 @@ import android.net.NetworkInfo.DetailedState;
|
|||||||
import android.net.StaticIpConfiguration;
|
import android.net.StaticIpConfiguration;
|
||||||
import android.net.ip.IpManager;
|
import android.net.ip.IpManager;
|
||||||
import android.net.ip.IpManager.ProvisioningConfiguration;
|
import android.net.ip.IpManager.ProvisioningConfiguration;
|
||||||
import android.net.ip.IpManager.WaitForProvisioningCallback;
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.INetworkManagementService;
|
import android.os.INetworkManagementService;
|
||||||
@@ -50,6 +49,8 @@ import com.android.server.net.BaseNetworkObserver;
|
|||||||
|
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,6 +85,9 @@ class EthernetNetworkFactory {
|
|||||||
/** To set link state and configure IP addresses. */
|
/** To set link state and configure IP addresses. */
|
||||||
private INetworkManagementService mNMService;
|
private INetworkManagementService mNMService;
|
||||||
|
|
||||||
|
/** All code runs here, including start(). */
|
||||||
|
private Handler mHandler;
|
||||||
|
|
||||||
/* To communicate with ConnectivityManager */
|
/* To communicate with ConnectivityManager */
|
||||||
private NetworkCapabilities mNetworkCapabilities;
|
private NetworkCapabilities mNetworkCapabilities;
|
||||||
private NetworkAgent mNetworkAgent;
|
private NetworkAgent mNetworkAgent;
|
||||||
@@ -96,19 +100,18 @@ class EthernetNetworkFactory {
|
|||||||
/** To notify Ethernet status. */
|
/** To notify Ethernet status. */
|
||||||
private final RemoteCallbackList<IEthernetServiceListener> mListeners;
|
private final RemoteCallbackList<IEthernetServiceListener> mListeners;
|
||||||
|
|
||||||
/** Data members. All accesses to these must be synchronized(this). */
|
/** Data members. All accesses to these must be on the handler thread. */
|
||||||
private static String mIface = "";
|
private String mIface = "";
|
||||||
private String mHwAddr;
|
private String mHwAddr;
|
||||||
private static boolean mLinkUp;
|
private boolean mLinkUp;
|
||||||
private NetworkInfo mNetworkInfo;
|
private NetworkInfo mNetworkInfo;
|
||||||
private LinkProperties mLinkProperties;
|
private LinkProperties mLinkProperties;
|
||||||
private IpManager mIpManager;
|
private IpManager mIpManager;
|
||||||
private Thread mIpProvisioningThread;
|
private boolean mNetworkRequested = false;
|
||||||
|
|
||||||
EthernetNetworkFactory(RemoteCallbackList<IEthernetServiceListener> listeners) {
|
EthernetNetworkFactory(RemoteCallbackList<IEthernetServiceListener> listeners) {
|
||||||
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, "");
|
|
||||||
mLinkProperties = new LinkProperties();
|
|
||||||
initNetworkCapabilities();
|
initNetworkCapabilities();
|
||||||
|
clearInfo();
|
||||||
mListeners = listeners;
|
mListeners = listeners;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,26 +121,40 @@ class EthernetNetworkFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void startNetwork() {
|
protected void startNetwork() {
|
||||||
onRequestNetwork();
|
if (!mNetworkRequested) {
|
||||||
}
|
mNetworkRequested = true;
|
||||||
protected void stopNetwork() {
|
maybeStartIpManager();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopIpManagerLocked() {
|
protected void stopNetwork() {
|
||||||
|
mNetworkRequested = false;
|
||||||
|
stopIpManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearInfo() {
|
||||||
|
mLinkProperties = new LinkProperties();
|
||||||
|
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, "");
|
||||||
|
mNetworkInfo.setExtraInfo(mHwAddr);
|
||||||
|
mNetworkInfo.setIsAvailable(isTrackingInterface());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopIpManager() {
|
||||||
if (mIpManager != null) {
|
if (mIpManager != null) {
|
||||||
mIpManager.shutdown();
|
mIpManager.shutdown();
|
||||||
mIpManager = null;
|
mIpManager = null;
|
||||||
}
|
}
|
||||||
|
// ConnectivityService will only forget our NetworkAgent if we send it a NetworkInfo object
|
||||||
|
// with a state of DISCONNECTED or SUSPENDED. So we can't simply clear our NetworkInfo here:
|
||||||
|
// that sets the state to IDLE, and ConnectivityService will still think we're connected.
|
||||||
|
//
|
||||||
|
mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr);
|
||||||
|
if (mNetworkAgent != null) {
|
||||||
|
updateAgent();
|
||||||
|
mNetworkAgent = null;
|
||||||
}
|
}
|
||||||
|
clearInfo();
|
||||||
private void stopIpProvisioningThreadLocked() {
|
|
||||||
stopIpManagerLocked();
|
|
||||||
|
|
||||||
if (mIpProvisioningThread != null) {
|
|
||||||
mIpProvisioningThread.interrupt();
|
|
||||||
mIpProvisioningThread = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -150,36 +167,36 @@ class EthernetNetworkFactory {
|
|||||||
}
|
}
|
||||||
Log.d(TAG, "updateInterface: " + iface + " link " + (up ? "up" : "down"));
|
Log.d(TAG, "updateInterface: " + iface + " link " + (up ? "up" : "down"));
|
||||||
|
|
||||||
synchronized(this) {
|
|
||||||
mLinkUp = up;
|
mLinkUp = up;
|
||||||
mNetworkInfo.setIsAvailable(up);
|
if (up) {
|
||||||
if (!up) {
|
maybeStartIpManager();
|
||||||
// Tell the agent we're disconnected. It will call disconnect().
|
} else {
|
||||||
mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr);
|
stopIpManager();
|
||||||
stopIpProvisioningThreadLocked();
|
|
||||||
}
|
|
||||||
updateAgent();
|
|
||||||
// set our score lower than any network could go
|
|
||||||
// so we get dropped. TODO - just unregister the factory
|
|
||||||
// when link goes down.
|
|
||||||
mFactory.setScoreFilter(up ? NETWORK_SCORE : -1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class InterfaceObserver extends BaseNetworkObserver {
|
private class InterfaceObserver extends BaseNetworkObserver {
|
||||||
@Override
|
@Override
|
||||||
public void interfaceLinkStateChanged(String iface, boolean up) {
|
public void interfaceLinkStateChanged(String iface, boolean up) {
|
||||||
|
mHandler.post(() -> {
|
||||||
updateInterfaceState(iface, up);
|
updateInterfaceState(iface, up);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void interfaceAdded(String iface) {
|
public void interfaceAdded(String iface) {
|
||||||
|
mHandler.post(() -> {
|
||||||
maybeTrackInterface(iface);
|
maybeTrackInterface(iface);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void interfaceRemoved(String iface) {
|
public void interfaceRemoved(String iface) {
|
||||||
stopTrackingInterface(iface);
|
mHandler.post(() -> {
|
||||||
|
if (stopTrackingInterface(iface)) {
|
||||||
|
trackFirstAvailableInterface();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,16 +212,14 @@ class EthernetNetworkFactory {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (this) {
|
|
||||||
if (!isTrackingInterface()) {
|
if (!isTrackingInterface()) {
|
||||||
setInterfaceInfoLocked(iface, config.getHardwareAddress());
|
setInterfaceInfo(iface, config.getHardwareAddress());
|
||||||
mNetworkInfo.setIsAvailable(true);
|
mNetworkInfo.setIsAvailable(true);
|
||||||
mNetworkInfo.setExtraInfo(mHwAddr);
|
mNetworkInfo.setExtraInfo(mHwAddr);
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "Interface unexpectedly changed from " + iface + " to " + mIface);
|
Log.e(TAG, "Interface unexpectedly changed from " + iface + " to " + mIface);
|
||||||
mNMService.setInterfaceDown(iface);
|
mNMService.setInterfaceDown(iface);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(TAG, "Error upping interface " + mIface + ": " + e);
|
Log.e(TAG, "Error upping interface " + mIface + ": " + e);
|
||||||
}
|
}
|
||||||
@@ -221,23 +236,14 @@ class EthernetNetworkFactory {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopTrackingInterface(String iface) {
|
private boolean stopTrackingInterface(String iface) {
|
||||||
if (!iface.equals(mIface))
|
if (!iface.equals(mIface))
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
Log.d(TAG, "Stopped tracking interface " + iface);
|
Log.d(TAG, "Stopped tracking interface " + iface);
|
||||||
// TODO: Unify this codepath with stop().
|
setInterfaceInfo("", null);
|
||||||
synchronized (this) {
|
stopIpManager();
|
||||||
stopIpProvisioningThreadLocked();
|
return true;
|
||||||
setInterfaceInfoLocked("", null);
|
|
||||||
mNetworkInfo.setExtraInfo(null);
|
|
||||||
mLinkUp = false;
|
|
||||||
mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr);
|
|
||||||
updateAgent();
|
|
||||||
mNetworkAgent = null;
|
|
||||||
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, "");
|
|
||||||
mLinkProperties = new LinkProperties();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean setStaticIpAddress(StaticIpConfiguration staticConfig) {
|
private boolean setStaticIpAddress(StaticIpConfiguration staticConfig) {
|
||||||
@@ -260,7 +266,6 @@ class EthernetNetworkFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void updateAgent() {
|
public void updateAgent() {
|
||||||
synchronized (EthernetNetworkFactory.this) {
|
|
||||||
if (mNetworkAgent == null) return;
|
if (mNetworkAgent == null) return;
|
||||||
if (DBG) {
|
if (DBG) {
|
||||||
Log.i(TAG, "Updating mNetworkAgent with: " +
|
Log.i(TAG, "Updating mNetworkAgent with: " +
|
||||||
@@ -274,21 +279,55 @@ class EthernetNetworkFactory {
|
|||||||
// never set the network score below 0.
|
// never set the network score below 0.
|
||||||
mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : 0);
|
mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : 0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Called by the NetworkFactory on the handler thread. */
|
void onIpLayerStarted(LinkProperties linkProperties) {
|
||||||
public void onRequestNetwork() {
|
if (mNetworkAgent != null) {
|
||||||
synchronized(EthernetNetworkFactory.this) {
|
Log.e(TAG, "Already have a NetworkAgent - aborting new request");
|
||||||
if (mIpProvisioningThread != null) {
|
stopIpManager();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
mLinkProperties = linkProperties;
|
||||||
|
mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr);
|
||||||
|
|
||||||
|
// Create our NetworkAgent.
|
||||||
|
mNetworkAgent = new NetworkAgent(mHandler.getLooper(), mContext,
|
||||||
|
NETWORK_TYPE, mNetworkInfo, mNetworkCapabilities, mLinkProperties,
|
||||||
|
NETWORK_SCORE) {
|
||||||
|
public void unwanted() {
|
||||||
|
if (this == mNetworkAgent) {
|
||||||
|
stopIpManager();
|
||||||
|
} else if (mNetworkAgent != null) {
|
||||||
|
Log.d(TAG, "Ignoring unwanted as we have a more modern " +
|
||||||
|
"instance");
|
||||||
|
} // Otherwise, we've already called stopIpManager.
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
final Thread ipProvisioningThread = new Thread(new Runnable() {
|
void onIpLayerStopped(LinkProperties linkProperties) {
|
||||||
public void run() {
|
// This cannot happen due to provisioning timeout, because our timeout is 0. It can only
|
||||||
|
// happen if we're provisioned and we lose provisioning.
|
||||||
|
stopIpManager();
|
||||||
|
maybeStartIpManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateLinkProperties(LinkProperties linkProperties) {
|
||||||
|
mLinkProperties = linkProperties;
|
||||||
|
if (mNetworkAgent != null) {
|
||||||
|
mNetworkAgent.sendLinkProperties(linkProperties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void maybeStartIpManager() {
|
||||||
|
if (mNetworkRequested && mIpManager == null && isTrackingInterface()) {
|
||||||
|
startIpManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startIpManager() {
|
||||||
if (DBG) {
|
if (DBG) {
|
||||||
Log.d(TAG, String.format("starting ipProvisioningThread(%s): mNetworkInfo=%s",
|
Log.d(TAG, String.format("starting IpManager(%s): mNetworkInfo=%s", mIface,
|
||||||
mIface, mNetworkInfo));
|
mNetworkInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
LinkProperties linkProperties;
|
LinkProperties linkProperties;
|
||||||
@@ -303,20 +342,24 @@ class EthernetNetworkFactory {
|
|||||||
linkProperties = config.getStaticIpConfiguration().toLinkProperties(mIface);
|
linkProperties = config.getStaticIpConfiguration().toLinkProperties(mIface);
|
||||||
} else {
|
} else {
|
||||||
mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr);
|
mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr);
|
||||||
WaitForProvisioningCallback ipmCallback = new WaitForProvisioningCallback() {
|
IpManager.Callback ipmCallback = new IpManager.Callback() {
|
||||||
|
@Override
|
||||||
|
public void onProvisioningSuccess(LinkProperties newLp) {
|
||||||
|
mHandler.post(() -> onIpLayerStarted(newLp));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProvisioningFailure(LinkProperties newLp) {
|
||||||
|
mHandler.post(() -> onIpLayerStopped(newLp));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLinkPropertiesChange(LinkProperties newLp) {
|
public void onLinkPropertiesChange(LinkProperties newLp) {
|
||||||
synchronized(EthernetNetworkFactory.this) {
|
mHandler.post(() -> updateLinkProperties(newLp));
|
||||||
if (mNetworkAgent != null && mNetworkInfo.isConnected()) {
|
|
||||||
mLinkProperties = newLp;
|
|
||||||
mNetworkAgent.sendLinkProperties(newLp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
synchronized(EthernetNetworkFactory.this) {
|
stopIpManager();
|
||||||
stopIpManagerLocked();
|
|
||||||
mIpManager = new IpManager(mContext, mIface, ipmCallback);
|
mIpManager = new IpManager(mContext, mIface, ipmCallback);
|
||||||
|
|
||||||
if (config.getProxySettings() == ProxySettings.STATIC ||
|
if (config.getProxySettings() == ProxySettings.STATIC ||
|
||||||
@@ -336,80 +379,14 @@ class EthernetNetworkFactory {
|
|||||||
.build();
|
.build();
|
||||||
mIpManager.startProvisioning(provisioningConfiguration);
|
mIpManager.startProvisioning(provisioningConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
linkProperties = ipmCallback.waitForProvisioning();
|
|
||||||
if (linkProperties == null) {
|
|
||||||
Log.e(TAG, "IP provisioning error");
|
|
||||||
// set our score lower than any network could go
|
|
||||||
// so we get dropped.
|
|
||||||
mFactory.setScoreFilter(-1);
|
|
||||||
synchronized(EthernetNetworkFactory.this) {
|
|
||||||
stopIpManagerLocked();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized(EthernetNetworkFactory.this) {
|
|
||||||
if (mNetworkAgent != null) {
|
|
||||||
Log.e(TAG, "Already have a NetworkAgent - aborting new request");
|
|
||||||
stopIpManagerLocked();
|
|
||||||
mIpProvisioningThread = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mLinkProperties = linkProperties;
|
|
||||||
mNetworkInfo.setIsAvailable(true);
|
|
||||||
mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr);
|
|
||||||
|
|
||||||
// Create our NetworkAgent.
|
|
||||||
mNetworkAgent = new NetworkAgent(mFactory.getLooper(), mContext,
|
|
||||||
NETWORK_TYPE, mNetworkInfo, mNetworkCapabilities, mLinkProperties,
|
|
||||||
NETWORK_SCORE) {
|
|
||||||
public void unwanted() {
|
|
||||||
synchronized(EthernetNetworkFactory.this) {
|
|
||||||
if (this == mNetworkAgent) {
|
|
||||||
stopIpManagerLocked();
|
|
||||||
|
|
||||||
mLinkProperties.clear();
|
|
||||||
mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null,
|
|
||||||
mHwAddr);
|
|
||||||
updateAgent();
|
|
||||||
mNetworkAgent = null;
|
|
||||||
try {
|
|
||||||
mNMService.clearInterfaceAddresses(mIface);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Failed to clear addresses or disable ipv6" + e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.d(TAG, "Ignoring unwanted as we have a more modern " +
|
|
||||||
"instance");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
mIpProvisioningThread = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DBG) {
|
|
||||||
Log.d(TAG, String.format("exiting ipProvisioningThread(%s): mNetworkInfo=%s",
|
|
||||||
mIface, mNetworkInfo));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
synchronized(EthernetNetworkFactory.this) {
|
|
||||||
if (mIpProvisioningThread == null) {
|
|
||||||
mIpProvisioningThread = ipProvisioningThread;
|
|
||||||
mIpProvisioningThread.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begin monitoring connectivity
|
* Begin monitoring connectivity
|
||||||
*/
|
*/
|
||||||
public synchronized void start(Context context, Handler target) {
|
public void start(Context context, Handler handler) {
|
||||||
|
mHandler = handler;
|
||||||
|
|
||||||
// The services we use.
|
// The services we use.
|
||||||
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
|
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
|
||||||
mNMService = INetworkManagementService.Stub.asInterface(b);
|
mNMService = INetworkManagementService.Stub.asInterface(b);
|
||||||
@@ -420,9 +397,9 @@ class EthernetNetworkFactory {
|
|||||||
com.android.internal.R.string.config_ethernet_iface_regex);
|
com.android.internal.R.string.config_ethernet_iface_regex);
|
||||||
|
|
||||||
// Create and register our NetworkFactory.
|
// Create and register our NetworkFactory.
|
||||||
mFactory = new LocalNetworkFactory(NETWORK_TYPE, context, target.getLooper());
|
mFactory = new LocalNetworkFactory(NETWORK_TYPE, context, mHandler.getLooper());
|
||||||
mFactory.setCapabilityFilter(mNetworkCapabilities);
|
mFactory.setCapabilityFilter(mNetworkCapabilities);
|
||||||
mFactory.setScoreFilter(-1); // this set high when we have an iface
|
mFactory.setScoreFilter(NETWORK_SCORE);
|
||||||
mFactory.register();
|
mFactory.register();
|
||||||
|
|
||||||
mContext = context;
|
mContext = context;
|
||||||
@@ -437,45 +414,32 @@ class EthernetNetworkFactory {
|
|||||||
|
|
||||||
// If an Ethernet interface is already connected, start tracking that.
|
// If an Ethernet interface is already connected, start tracking that.
|
||||||
// Otherwise, the first Ethernet interface to appear will be tracked.
|
// Otherwise, the first Ethernet interface to appear will be tracked.
|
||||||
|
mHandler.post(() -> trackFirstAvailableInterface());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void trackFirstAvailableInterface() {
|
||||||
try {
|
try {
|
||||||
final String[] ifaces = mNMService.listInterfaces();
|
final String[] ifaces = mNMService.listInterfaces();
|
||||||
for (String iface : ifaces) {
|
for (String iface : ifaces) {
|
||||||
synchronized(this) {
|
|
||||||
if (maybeTrackInterface(iface)) {
|
if (maybeTrackInterface(iface)) {
|
||||||
// We have our interface. Track it.
|
// We have our interface. Track it.
|
||||||
// Note: if the interface already has link (e.g., if we
|
// Note: if the interface already has link (e.g., if we crashed and got
|
||||||
// crashed and got restarted while it was running),
|
// restarted while it was running), we need to fake a link up notification so we
|
||||||
// we need to fake a link up notification so we start
|
// start configuring it.
|
||||||
// configuring it. Since we're already holding the lock,
|
|
||||||
// any real link up/down notification will only arrive
|
|
||||||
// after we've done this.
|
|
||||||
if (mNMService.getInterfaceConfig(iface).hasFlag("running")) {
|
if (mNMService.getInterfaceConfig(iface).hasFlag("running")) {
|
||||||
updateInterfaceState(iface, true);
|
updateInterfaceState(iface, true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} catch (RemoteException|IllegalStateException e) {
|
} catch (RemoteException|IllegalStateException e) {
|
||||||
Log.e(TAG, "Could not get list of interfaces " + e);
|
Log.e(TAG, "Could not get list of interfaces " + e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void stop() {
|
public void stop() {
|
||||||
stopIpProvisioningThreadLocked();
|
stopIpManager();
|
||||||
// ConnectivityService will only forget our NetworkAgent if we send it a NetworkInfo object
|
setInterfaceInfo("", null);
|
||||||
// with a state of DISCONNECTED or SUSPENDED. So we can't simply clear our NetworkInfo here:
|
|
||||||
// that sets the state to IDLE, and ConnectivityService will still think we're connected.
|
|
||||||
//
|
|
||||||
// TODO: stop using explicit comparisons to DISCONNECTED / SUSPENDED in ConnectivityService,
|
|
||||||
// and instead use isConnectedOrConnecting().
|
|
||||||
mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr);
|
|
||||||
mLinkUp = false;
|
|
||||||
updateAgent();
|
|
||||||
mLinkProperties = new LinkProperties();
|
|
||||||
mNetworkAgent = null;
|
|
||||||
setInterfaceInfoLocked("", null);
|
|
||||||
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, "");
|
|
||||||
mFactory.unregister();
|
mFactory.unregister();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,20 +453,22 @@ class EthernetNetworkFactory {
|
|||||||
mNetworkCapabilities.setLinkDownstreamBandwidthKbps(100 * 1000);
|
mNetworkCapabilities.setLinkDownstreamBandwidthKbps(100 * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean isTrackingInterface() {
|
public boolean isTrackingInterface() {
|
||||||
return !TextUtils.isEmpty(mIface);
|
return !TextUtils.isEmpty(mIface);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set interface information and notify listeners if availability is changed.
|
* Set interface information and notify listeners if availability is changed.
|
||||||
* This should be called with the lock held.
|
|
||||||
*/
|
*/
|
||||||
private void setInterfaceInfoLocked(String iface, String hwAddr) {
|
private void setInterfaceInfo(String iface, String hwAddr) {
|
||||||
boolean oldAvailable = isTrackingInterface();
|
boolean oldAvailable = isTrackingInterface();
|
||||||
mIface = iface;
|
mIface = iface;
|
||||||
mHwAddr = hwAddr;
|
mHwAddr = hwAddr;
|
||||||
boolean available = isTrackingInterface();
|
boolean available = isTrackingInterface();
|
||||||
|
|
||||||
|
mNetworkInfo.setExtraInfo(mHwAddr);
|
||||||
|
mNetworkInfo.setIsAvailable(available);
|
||||||
|
|
||||||
if (oldAvailable != available) {
|
if (oldAvailable != available) {
|
||||||
int n = mListeners.beginBroadcast();
|
int n = mListeners.beginBroadcast();
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
@@ -516,7 +482,23 @@ class EthernetNetworkFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
|
private void postAndWaitForRunnable(Runnable r) throws InterruptedException {
|
||||||
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
mHandler.post(() -> {
|
||||||
|
try {
|
||||||
|
r.run();
|
||||||
|
} finally {
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
latch.await();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
|
||||||
|
try {
|
||||||
|
postAndWaitForRunnable(() -> {
|
||||||
|
pw.println("Network Requested: " + mNetworkRequested);
|
||||||
if (isTrackingInterface()) {
|
if (isTrackingInterface()) {
|
||||||
pw.println("Tracking interface: " + mIface);
|
pw.println("Tracking interface: " + mIface);
|
||||||
pw.increaseIndent();
|
pw.increaseIndent();
|
||||||
@@ -537,5 +519,9 @@ class EthernetNetworkFactory {
|
|||||||
mIpManager.dump(fd, pw, args);
|
mIpManager.dump(fd, pw, args);
|
||||||
pw.decreaseIndent();
|
pw.decreaseIndent();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new IllegalStateException("dump() interrupted");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user