Apply refactored NetworkFactory.

Make NetworkFactory a concrete class and divide responsibilites between it and NetworkAgent.
Factory will track requests and by default give a single connect/disconnect api for ease
of use.  Then NetworkAgent is created and destroyed as needed with very simple logic.

Change-Id: I401c14a6e5466f2fc63b04219b97ff85bb9af291
(cherry picked from commit 8af038d056)
This commit is contained in:
Robert Greenwalt
2014-05-27 17:59:24 -07:00
parent 0ffeaf5c76
commit 301c18a01d

View File

@@ -18,7 +18,6 @@ package com.android.server.ethernet;
import android.content.Context; import android.content.Context;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.ConnectivityServiceProtocol.NetworkFactoryProtocol;
import android.net.DhcpResults; import android.net.DhcpResults;
import android.net.InterfaceConfiguration; import android.net.InterfaceConfiguration;
import android.net.NetworkUtils; import android.net.NetworkUtils;
@@ -29,6 +28,7 @@ import android.net.LinkAddress;
import android.net.LinkProperties; import android.net.LinkProperties;
import android.net.NetworkAgent; import android.net.NetworkAgent;
import android.net.NetworkCapabilities; import android.net.NetworkCapabilities;
import android.net.NetworkFactory;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState; import android.net.NetworkInfo.DetailedState;
import android.net.NetworkRequest; import android.net.NetworkRequest;
@@ -51,51 +51,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
class NetworkFactory extends Handler {
public interface Callback {
public void onRequestNetwork(NetworkRequest request, int currentScore);
public void onCancelRequest(NetworkRequest request);
}
private String mName;
private Callback mCallback;
private ConnectivityManager mCM;
NetworkFactory(String name, Context context, Looper looper, Callback callback) {
super(looper);
mCallback = callback;
mName = name;
mCM = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
}
public void register() {
logi("Registering network factory");
mCM.registerNetworkFactory(new Messenger(this), mName);
}
@Override
public void handleMessage(Message message) {
switch(message.what) {
case NetworkFactoryProtocol.CMD_REQUEST_NETWORK:
mCallback.onRequestNetwork((NetworkRequest) message.obj, message.arg1);
break;
case NetworkFactoryProtocol.CMD_CANCEL_REQUEST:
mCallback.onCancelRequest((NetworkRequest) message.obj);
break;
default:
loge("Unhandled message " + message.what);
}
}
private void logi(String s) {
Log.i("NetworkFactory" + mName, s);
}
private void loge(String s) {
Log.e("NetworkFactory" + mName, s);
}
}
/** /**
* Manages connectivity for an Ethernet interface. * Manages connectivity for an Ethernet interface.
* *
@@ -113,8 +68,8 @@ class NetworkFactory extends Handler {
* *
* @hide * @hide
*/ */
class EthernetNetworkFactory implements NetworkFactory.Callback { class EthernetNetworkFactory {
private static final String NETWORK_TYPE = "ETHERNET"; private static final String NETWORK_TYPE = "Ethernet";
private static final String TAG = "EthernetNetworkFactory"; private static final String TAG = "EthernetNetworkFactory";
private static final int NETWORK_SCORE = 70; private static final int NETWORK_SCORE = 70;
private static final boolean DBG = true; private static final boolean DBG = true;
@@ -131,7 +86,8 @@ class EthernetNetworkFactory implements NetworkFactory.Callback {
/* To communicate with ConnectivityManager */ /* To communicate with ConnectivityManager */
private NetworkCapabilities mNetworkCapabilities; private NetworkCapabilities mNetworkCapabilities;
private NetworkAgent mNetworkAgent; private NetworkAgent mNetworkAgent;
private NetworkFactory mFactory; private LocalNetworkFactory mFactory;
private Context mContext;
/** Product-dependent regular expression of interface names we track. */ /** Product-dependent regular expression of interface names we track. */
private static String mIfaceMatch = ""; private static String mIfaceMatch = "";
@@ -149,6 +105,20 @@ class EthernetNetworkFactory implements NetworkFactory.Callback {
initNetworkCapabilities(); initNetworkCapabilities();
} }
private class LocalNetworkFactory extends NetworkFactory {
LocalNetworkFactory(String name, Context context, Looper looper) {
super(looper, context, name, new NetworkCapabilities());
}
protected void startNetwork() {
onRequestNetwork();
}
protected void stopNetwork() {
onCancelRequest();
}
}
/** /**
* Updates interface state variables. * Updates interface state variables.
* Called on link state changes or on startup. * Called on link state changes or on startup.
@@ -166,8 +136,9 @@ class EthernetNetworkFactory implements NetworkFactory.Callback {
// Tell the agent we're disconnected. It will call disconnect(). // Tell the agent we're disconnected. It will call disconnect().
mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr); mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr);
} }
mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : 0); mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : -1);
updateAgent(); updateAgent();
mFactory.setScoreFilter(up ? NETWORK_SCORE : -1);
} }
} }
@@ -232,7 +203,7 @@ class EthernetNetworkFactory implements NetworkFactory.Callback {
return; return;
Log.d(TAG, "Stopped tracking interface " + iface); Log.d(TAG, "Stopped tracking interface " + iface);
disconnect(); onCancelRequest();
synchronized (this) { synchronized (this) {
mIface = ""; mIface = "";
mHwAddr = null; mHwAddr = null;
@@ -262,46 +233,28 @@ class EthernetNetworkFactory implements NetworkFactory.Callback {
} }
} }
public synchronized void updateAgent() { public void updateAgent() {
if (DBG) { synchronized (EthernetNetworkFactory.this) {
Log.i(TAG, "Updating mNetworkAgent with: " + if (mNetworkAgent == null) return;
mNetworkCapabilities + ", " + if (DBG) {
mNetworkInfo + ", " + Log.i(TAG, "Updating mNetworkAgent with: " +
mLinkProperties); mNetworkCapabilities + ", " +
mNetworkInfo + ", " +
mLinkProperties);
}
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
mNetworkAgent.sendNetworkInfo(mNetworkInfo);
mNetworkAgent.sendLinkProperties(mLinkProperties);
mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : -1);
} }
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
// Send LinkProperties before NetworkInfo.
//
// This is because if we just connected, as soon as we send the agent a
// connected NetworkInfo, the agent will register with CS, and at that
// point the current LinkProperties will be empty, with no IP
// addresses, DNS servers or routes, only an interface name. (The
// agent will refuse to register if LinkProperties are null, but not if
// they are "empty" like this.)
//
// This causes two problems:
//
// 1. ConnectivityService brings up the network with empty
// LinkProperties, and thus no routes and no DNS servers.
// 2. When we do send LinkProperties immediately after that, the agent
// does not pass them on to ConnectivityService because its
// mAsyncChannel is null.
//
// TODO: Fix NetworkAgent to make sure that sending updates just after
// connecting works properly.
mNetworkAgent.sendLinkProperties(mLinkProperties);
mNetworkAgent.sendNetworkInfo(mNetworkInfo);
} }
/* Called by the NetworkAgent on the handler thread. */ /* Called by the NetworkFactory on the handler thread. */
public void connect() { public void onRequestNetwork() {
// TODO: Handle DHCP renew.
Thread dhcpThread = new Thread(new Runnable() { Thread dhcpThread = new Thread(new Runnable() {
public void run() { public void run() {
if (DBG) Log.i(TAG, "dhcpThread: mNetworkInfo=" + mNetworkInfo); if (DBG) Log.i(TAG, "dhcpThread(+" + mIface + "): mNetworkInfo=" + mNetworkInfo);
synchronized(this) {
mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr);
updateAgent();
}
LinkProperties linkProperties; LinkProperties linkProperties;
IpConfiguration config = mEthernetManager.getConfiguration(); IpConfiguration config = mEthernetManager.getConfiguration();
@@ -310,6 +263,11 @@ class EthernetNetworkFactory implements NetworkFactory.Callback {
linkProperties = config.linkProperties; linkProperties = config.linkProperties;
setStaticIpAddress(linkProperties); setStaticIpAddress(linkProperties);
} else { } else {
mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr);
synchronized (EthernetNetworkFactory.this) {
mNetworkAgent.sendNetworkInfo(mNetworkInfo);
}
DhcpResults dhcpResults = new DhcpResults(); DhcpResults dhcpResults = new DhcpResults();
// TODO: Handle DHCP renewals better. // TODO: Handle DHCP renewals better.
// In general runDhcp handles DHCP renewals for us, because // In general runDhcp handles DHCP renewals for us, because
@@ -323,8 +281,9 @@ class EthernetNetworkFactory implements NetworkFactory.Callback {
// of 0, and it will call disconnect for us. We'll // of 0, and it will call disconnect for us. We'll
// attempt to reconnect when we next see a link up // attempt to reconnect when we next see a link up
// event, which resets the score to NETWORK_SCORE. // event, which resets the score to NETWORK_SCORE.
mNetworkAgent.sendNetworkScore(0); mNetworkAgent.sendNetworkScore(-1);
} }
mFactory.setScoreFilter(-1);
return; return;
} }
linkProperties = dhcpResults.linkProperties; linkProperties = dhcpResults.linkProperties;
@@ -338,7 +297,15 @@ class EthernetNetworkFactory implements NetworkFactory.Callback {
mLinkProperties = linkProperties; mLinkProperties = linkProperties;
mNetworkInfo.setIsAvailable(true); mNetworkInfo.setIsAvailable(true);
mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr); mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr);
updateAgent();
// Create our NetworkAgent.
mNetworkAgent = new NetworkAgent(mFactory.getLooper(), mContext,
NETWORK_TYPE, mNetworkInfo, mNetworkCapabilities, mLinkProperties,
NETWORK_SCORE) {
public void unwanted() {
EthernetNetworkFactory.this.onCancelRequest();
};
};
} }
} }
}); });
@@ -350,14 +317,14 @@ class EthernetNetworkFactory implements NetworkFactory.Callback {
* Does not touch interface state variables such as link state and MAC address. * Does not touch interface state variables such as link state and MAC address.
* Called when the tracked interface loses link or disappears. * Called when the tracked interface loses link or disappears.
*/ */
public void disconnect() { public void onCancelRequest() {
NetworkUtils.stopDhcp(mIface); NetworkUtils.stopDhcp(mIface);
synchronized(this) { synchronized(this) {
mLinkProperties.clear(); mLinkProperties.clear();
mNetworkInfo.setIsAvailable(false);
mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr); mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr);
updateAgent(); updateAgent();
mNetworkAgent = null;
} }
try { try {
@@ -380,25 +347,14 @@ class EthernetNetworkFactory implements NetworkFactory.Callback {
mIfaceMatch = context.getResources().getString( mIfaceMatch = context.getResources().getString(
com.android.internal.R.string.config_ethernet_iface_regex); com.android.internal.R.string.config_ethernet_iface_regex);
// Create our NetworkAgent.
mNetworkAgent = new NetworkAgent(target.getLooper(), context, NETWORK_TYPE) {
public synchronized void sendNetworkScore(int score) {
Log.i(TAG, "sendNetworkScore(" + score + ")");
super.sendNetworkScore(score);
}
public void connect() {
EthernetNetworkFactory.this.connect();
};
public void disconnect() {
EthernetNetworkFactory.this.disconnect();
};
};
mNetworkAgent.sendNetworkScore(0);
// Create and register our NetworkFactory. // Create and register our NetworkFactory.
mFactory = new NetworkFactory(NETWORK_TYPE, context, target.getLooper(), this); mFactory = new LocalNetworkFactory(NETWORK_TYPE, context, target.getLooper());
mFactory.setCapabilityFilter(mNetworkCapabilities);
mFactory.setScoreFilter(-1); // this set high when we have an iface
mFactory.register(); mFactory.register();
mContext = context;
// Start tracking interface change events. // Start tracking interface change events.
mInterfaceObserver = new InterfaceObserver(); mInterfaceObserver = new InterfaceObserver();
try { try {
@@ -434,18 +390,13 @@ class EthernetNetworkFactory implements NetworkFactory.Callback {
} }
public synchronized void stop() { public synchronized void stop() {
stopTrackingInterface(mIface); onCancelRequest();
} mIface = "";
mHwAddr = null;
public void onRequestNetwork(NetworkRequest request, int currentScore) { mLinkUp = false;
Log.i(TAG, "onRequestNetwork: (" + currentScore + "): " + request); mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, "");
// TODO check that the transport is compatible. mLinkProperties = new LinkProperties();
mNetworkAgent.addNetworkRequest(request, currentScore); mFactory.unregister();
}
public void onCancelRequest(NetworkRequest request) {
Log.i(TAG, "onCancelRequest: " + request);
mNetworkAgent.removeNetworkRequest(request);
} }
private void initNetworkCapabilities() { private void initNetworkCapabilities() {