Merge "More correctly track upstream network properties." into nyc-mr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
5cbbc02a0f
@@ -591,13 +591,13 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
|||||||
synchronized (mPublicSync) {
|
synchronized (mPublicSync) {
|
||||||
TetherState tetherState = mTetherStates.get(iface);
|
TetherState tetherState = mTetherStates.get(iface);
|
||||||
if (tetherState == null) {
|
if (tetherState == null) {
|
||||||
Log.e(TAG, "Tried to Tether an unknown iface :" + iface + ", ignoring");
|
Log.e(TAG, "Tried to Tether an unknown iface: " + iface + ", ignoring");
|
||||||
return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
|
return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
|
||||||
}
|
}
|
||||||
// Ignore the error status of the interface. If the interface is available,
|
// Ignore the error status of the interface. If the interface is available,
|
||||||
// the errors are referring to past tethering attempts anyway.
|
// the errors are referring to past tethering attempts anyway.
|
||||||
if (tetherState.mLastState != IControlsTethering.STATE_AVAILABLE) {
|
if (tetherState.mLastState != IControlsTethering.STATE_AVAILABLE) {
|
||||||
Log.e(TAG, "Tried to Tether an unavailable iface :" + iface + ", ignoring");
|
Log.e(TAG, "Tried to Tether an unavailable iface: " + iface + ", ignoring");
|
||||||
return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
|
return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
|
||||||
}
|
}
|
||||||
tetherState.mStateMachine.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED);
|
tetherState.mStateMachine.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED);
|
||||||
@@ -1017,16 +1017,30 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
|||||||
* tethering master state machine thread for subsequent processing.
|
* tethering master state machine thread for subsequent processing.
|
||||||
*/
|
*/
|
||||||
class UpstreamNetworkCallback extends NetworkCallback {
|
class UpstreamNetworkCallback extends NetworkCallback {
|
||||||
|
@Override
|
||||||
|
public void onAvailable(Network network) {
|
||||||
|
mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
|
||||||
|
UpstreamNetworkMonitor.EVENT_ON_AVAILABLE, 0, network);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCapabilitiesChanged(Network network, NetworkCapabilities newNc) {
|
||||||
|
mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
|
||||||
|
UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES, 0,
|
||||||
|
new NetworkState(null, null, newNc, network, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLinkPropertiesChanged(Network network, LinkProperties newLp) {
|
public void onLinkPropertiesChanged(Network network, LinkProperties newLp) {
|
||||||
mTetherMasterSM.sendMessage(
|
mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
|
||||||
TetherMasterSM.EVENT_UPSTREAM_LINKPROPERTIES_CHANGED,
|
UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES, 0,
|
||||||
new NetworkState(null, newLp, null, network, null, null));
|
new NetworkState(null, newLp, null, network, null, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLost(Network network) {
|
public void onLost(Network network) {
|
||||||
mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_LOST, network);
|
mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
|
||||||
|
UpstreamNetworkMonitor.EVENT_ON_LOST, 0, network);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1045,6 +1059,11 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
|||||||
* could/should be moved here.
|
* could/should be moved here.
|
||||||
*/
|
*/
|
||||||
class UpstreamNetworkMonitor {
|
class UpstreamNetworkMonitor {
|
||||||
|
static final int EVENT_ON_AVAILABLE = 1;
|
||||||
|
static final int EVENT_ON_CAPABILITIES = 2;
|
||||||
|
static final int EVENT_ON_LINKPROPERTIES = 3;
|
||||||
|
static final int EVENT_ON_LOST = 4;
|
||||||
|
|
||||||
final HashMap<Network, NetworkState> mNetworkMap = new HashMap<>();
|
final HashMap<Network, NetworkState> mNetworkMap = new HashMap<>();
|
||||||
NetworkCallback mDefaultNetworkCallback;
|
NetworkCallback mDefaultNetworkCallback;
|
||||||
NetworkCallback mDunTetheringCallback;
|
NetworkCallback mDunTetheringCallback;
|
||||||
@@ -1079,20 +1098,101 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
|||||||
mNetworkMap.clear();
|
mNetworkMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if these updated LinkProperties pertain to the current
|
NetworkState lookup(Network network) {
|
||||||
// upstream network interface, false otherwise (or if there is not
|
return (network != null) ? mNetworkMap.get(network) : null;
|
||||||
// currently any upstream tethering interface).
|
|
||||||
boolean processLinkPropertiesChanged(NetworkState networkState) {
|
|
||||||
if (networkState == null ||
|
|
||||||
networkState.network == null ||
|
|
||||||
networkState.linkProperties == null) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mNetworkMap.put(networkState.network, networkState);
|
NetworkState processCallback(int arg1, Object obj) {
|
||||||
|
switch (arg1) {
|
||||||
|
case EVENT_ON_AVAILABLE: {
|
||||||
|
final Network network = (Network) obj;
|
||||||
|
if (VDBG) {
|
||||||
|
Log.d(TAG, "EVENT_ON_AVAILABLE for " + network);
|
||||||
|
}
|
||||||
|
if (!mNetworkMap.containsKey(network)) {
|
||||||
|
mNetworkMap.put(network,
|
||||||
|
new NetworkState(null, null, null, network, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
if (mCurrentUpstreamIface != null) {
|
final ConnectivityManager cm = getConnectivityManager();
|
||||||
for (String ifname : networkState.linkProperties.getAllInterfaceNames()) {
|
|
||||||
|
if (mDefaultNetworkCallback != null) {
|
||||||
|
cm.requestNetworkCapabilities(mDefaultNetworkCallback);
|
||||||
|
cm.requestLinkProperties(mDefaultNetworkCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requesting updates for mDunTetheringCallback is not
|
||||||
|
// necessary. Because it's a listen, it will already have
|
||||||
|
// heard all NetworkCapabilities and LinkProperties updates
|
||||||
|
// since UpstreamNetworkMonitor was started. Because we
|
||||||
|
// start UpstreamNetworkMonitor before chooseUpstreamType()
|
||||||
|
// is ever invoked (it can register a DUN request) this is
|
||||||
|
// mostly safe. However, if a DUN network is already up for
|
||||||
|
// some reason (unlikely, because DUN is restricted and,
|
||||||
|
// unless the DUN network is shared with another APN, only
|
||||||
|
// the system can request it and this is the only part of
|
||||||
|
// the system that requests it) we won't know its
|
||||||
|
// LinkProperties or NetworkCapabilities.
|
||||||
|
|
||||||
|
return mNetworkMap.get(network);
|
||||||
|
}
|
||||||
|
case EVENT_ON_CAPABILITIES: {
|
||||||
|
final NetworkState ns = (NetworkState) obj;
|
||||||
|
if (!mNetworkMap.containsKey(ns.network)) {
|
||||||
|
// Ignore updates for networks for which we have not yet
|
||||||
|
// received onAvailable() - which should never happen -
|
||||||
|
// or for which we have already received onLost().
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (VDBG) {
|
||||||
|
Log.d(TAG, String.format("EVENT_ON_CAPABILITIES for %s: %s",
|
||||||
|
ns.network, ns.networkCapabilities));
|
||||||
|
}
|
||||||
|
|
||||||
|
final NetworkState prev = mNetworkMap.get(ns.network);
|
||||||
|
mNetworkMap.put(ns.network,
|
||||||
|
new NetworkState(null, prev.linkProperties, ns.networkCapabilities,
|
||||||
|
ns.network, null, null));
|
||||||
|
return mNetworkMap.get(ns.network);
|
||||||
|
}
|
||||||
|
case EVENT_ON_LINKPROPERTIES: {
|
||||||
|
final NetworkState ns = (NetworkState) obj;
|
||||||
|
if (!mNetworkMap.containsKey(ns.network)) {
|
||||||
|
// Ignore updates for networks for which we have not yet
|
||||||
|
// received onAvailable() - which should never happen -
|
||||||
|
// or for which we have already received onLost().
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (VDBG) {
|
||||||
|
Log.d(TAG, String.format("EVENT_ON_LINKPROPERTIES for %s: %s",
|
||||||
|
ns.network, ns.linkProperties));
|
||||||
|
}
|
||||||
|
|
||||||
|
final NetworkState prev = mNetworkMap.get(ns.network);
|
||||||
|
mNetworkMap.put(ns.network,
|
||||||
|
new NetworkState(null, ns.linkProperties, prev.networkCapabilities,
|
||||||
|
ns.network, null, null));
|
||||||
|
return mNetworkMap.get(ns.network);
|
||||||
|
}
|
||||||
|
case EVENT_ON_LOST: {
|
||||||
|
final Network network = (Network) obj;
|
||||||
|
if (VDBG) {
|
||||||
|
Log.d(TAG, "EVENT_ON_LOST for " + network);
|
||||||
|
}
|
||||||
|
return mNetworkMap.remove(network);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Needed because the canonical source of upstream truth is just the
|
||||||
|
// upstream interface name, |mCurrentUpstreamIface|. This is ripe for
|
||||||
|
// future simplification, once the upstream Network is canonical.
|
||||||
|
boolean pertainsToCurrentUpstream(NetworkState ns) {
|
||||||
|
if (ns != null && ns.linkProperties != null && mCurrentUpstreamIface != null) {
|
||||||
|
for (String ifname : ns.linkProperties.getAllInterfaceNames()) {
|
||||||
if (mCurrentUpstreamIface.equals(ifname)) {
|
if (mCurrentUpstreamIface.equals(ifname)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1101,13 +1201,6 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void processNetworkLost(Network network) {
|
|
||||||
if (network != null) {
|
|
||||||
mNetworkMap.remove(network);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TetherMasterSM extends StateMachine {
|
class TetherMasterSM extends StateMachine {
|
||||||
private static final int BASE_MASTER = Protocol.BASE_TETHERING;
|
private static final int BASE_MASTER = Protocol.BASE_TETHERING;
|
||||||
// an interface SM has requested Tethering
|
// an interface SM has requested Tethering
|
||||||
@@ -1120,8 +1213,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
|||||||
static final int CMD_RETRY_UPSTREAM = BASE_MASTER + 4;
|
static final int CMD_RETRY_UPSTREAM = BASE_MASTER + 4;
|
||||||
// Events from NetworkCallbacks that we process on the master state
|
// Events from NetworkCallbacks that we process on the master state
|
||||||
// machine thread on behalf of the UpstreamNetworkMonitor.
|
// machine thread on behalf of the UpstreamNetworkMonitor.
|
||||||
static final int EVENT_UPSTREAM_LINKPROPERTIES_CHANGED = BASE_MASTER + 5;
|
static final int EVENT_UPSTREAM_CALLBACK = BASE_MASTER + 5;
|
||||||
static final int EVENT_UPSTREAM_LOST = BASE_MASTER + 6;
|
|
||||||
|
|
||||||
private State mInitialState;
|
private State mInitialState;
|
||||||
private State mTetherModeAliveState;
|
private State mTetherModeAliveState;
|
||||||
@@ -1278,6 +1370,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void chooseUpstreamType(boolean tryCell) {
|
protected void chooseUpstreamType(boolean tryCell) {
|
||||||
|
final ConnectivityManager cm = getConnectivityManager();
|
||||||
int upType = ConnectivityManager.TYPE_NONE;
|
int upType = ConnectivityManager.TYPE_NONE;
|
||||||
String iface = null;
|
String iface = null;
|
||||||
|
|
||||||
@@ -1292,8 +1385,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (Integer netType : mUpstreamIfaceTypes) {
|
for (Integer netType : mUpstreamIfaceTypes) {
|
||||||
NetworkInfo info =
|
NetworkInfo info = cm.getNetworkInfo(netType.intValue());
|
||||||
getConnectivityManager().getNetworkInfo(netType.intValue());
|
|
||||||
if ((info != null) && info.isConnected()) {
|
if ((info != null) && info.isConnected()) {
|
||||||
upType = netType.intValue();
|
upType = netType.intValue();
|
||||||
break;
|
break;
|
||||||
@@ -1334,9 +1426,9 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Network network = null;
|
||||||
if (upType != ConnectivityManager.TYPE_NONE) {
|
if (upType != ConnectivityManager.TYPE_NONE) {
|
||||||
LinkProperties linkProperties =
|
LinkProperties linkProperties = cm.getLinkProperties(upType);
|
||||||
getConnectivityManager().getLinkProperties(upType);
|
|
||||||
if (linkProperties != null) {
|
if (linkProperties != null) {
|
||||||
// Find the interface with the default IPv4 route. It may be the
|
// Find the interface with the default IPv4 route. It may be the
|
||||||
// interface described by linkProperties, or one of the interfaces
|
// interface described by linkProperties, or one of the interfaces
|
||||||
@@ -1353,7 +1445,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (iface != null) {
|
if (iface != null) {
|
||||||
Network network = getConnectivityManager().getNetworkForType(upType);
|
network = cm.getNetworkForType(upType);
|
||||||
if (network == null) {
|
if (network == null) {
|
||||||
Log.e(TAG, "No Network for upstream type " + upType + "!");
|
Log.e(TAG, "No Network for upstream type " + upType + "!");
|
||||||
}
|
}
|
||||||
@@ -1361,6 +1453,13 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
notifyTetheredOfNewUpstreamIface(iface);
|
notifyTetheredOfNewUpstreamIface(iface);
|
||||||
|
NetworkState ns = mUpstreamNetworkMonitor.lookup(network);
|
||||||
|
if (ns != null && pertainsToCurrentUpstream(ns)) {
|
||||||
|
// If we already have NetworkState for this network examine
|
||||||
|
// it immediately, because there likely will be no second
|
||||||
|
// EVENT_ON_AVAILABLE (it was already received).
|
||||||
|
handleNewUpstreamNetworkState(ns);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setDnsForwarders(final Network network, final LinkProperties lp) {
|
protected void setDnsForwarders(final Network network, final LinkProperties lp) {
|
||||||
@@ -1393,6 +1492,10 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
|||||||
ifaceName);
|
ifaceName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void handleNewUpstreamNetworkState(NetworkState ns) {
|
||||||
|
mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final AtomicInteger mSimBcastGenerationNumber = new AtomicInteger(0);
|
private final AtomicInteger mSimBcastGenerationNumber = new AtomicInteger(0);
|
||||||
@@ -1582,11 +1685,18 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
|||||||
chooseUpstreamType(mTryCell);
|
chooseUpstreamType(mTryCell);
|
||||||
mTryCell = !mTryCell;
|
mTryCell = !mTryCell;
|
||||||
break;
|
break;
|
||||||
case EVENT_UPSTREAM_LINKPROPERTIES_CHANGED:
|
case EVENT_UPSTREAM_CALLBACK: {
|
||||||
NetworkState state = (NetworkState) message.obj;
|
// First: always update local state about every network.
|
||||||
if (mUpstreamNetworkMonitor.processLinkPropertiesChanged(state)) {
|
final NetworkState ns = mUpstreamNetworkMonitor.processCallback(
|
||||||
setDnsForwarders(state.network, state.linkProperties);
|
message.arg1, message.obj);
|
||||||
} else if (mCurrentUpstreamIface == null) {
|
|
||||||
|
if (ns == null || !pertainsToCurrentUpstream(ns)) {
|
||||||
|
// TODO: In future, this is where upstream evaluation and selection
|
||||||
|
// could be handled for notifications which include sufficient data.
|
||||||
|
// For example, after CONNECTIVITY_ACTION listening is removed, here
|
||||||
|
// is where we could observe a Wi-Fi network becoming available and
|
||||||
|
// passing validation.
|
||||||
|
if (mCurrentUpstreamIface == null) {
|
||||||
// If we have no upstream interface, try to run through upstream
|
// If we have no upstream interface, try to run through upstream
|
||||||
// selection again. If, for example, IPv4 connectivity has shown up
|
// selection again. If, for example, IPv4 connectivity has shown up
|
||||||
// after IPv6 (e.g., 464xlat became available) we want the chance to
|
// after IPv6 (e.g., 464xlat became available) we want the chance to
|
||||||
@@ -1594,12 +1704,36 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
|||||||
chooseUpstreamType(false);
|
chooseUpstreamType(false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EVENT_UPSTREAM_LOST:
|
}
|
||||||
// TODO: Re-evaluate possible upstreams. Currently upstream reevaluation
|
|
||||||
// is triggered via received CONNECTIVITY_ACTION broadcasts that result
|
switch (message.arg1) {
|
||||||
// in being passed a TetherMasterSM.CMD_UPSTREAM_CHANGED.
|
case UpstreamNetworkMonitor.EVENT_ON_AVAILABLE:
|
||||||
mUpstreamNetworkMonitor.processNetworkLost((Network) message.obj);
|
// The default network changed, or DUN connected
|
||||||
|
// before this callback was processed. Updates
|
||||||
|
// for the current NetworkCapabilities and
|
||||||
|
// LinkProperties have been requested (default
|
||||||
|
// request) or are being sent shortly (DUN). Do
|
||||||
|
// nothing until they arrive; if no updates
|
||||||
|
// arrive there's nothing to do.
|
||||||
break;
|
break;
|
||||||
|
case UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES:
|
||||||
|
handleNewUpstreamNetworkState(ns);
|
||||||
|
break;
|
||||||
|
case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES:
|
||||||
|
setDnsForwarders(ns.network, ns.linkProperties);
|
||||||
|
handleNewUpstreamNetworkState(ns);
|
||||||
|
break;
|
||||||
|
case UpstreamNetworkMonitor.EVENT_ON_LOST:
|
||||||
|
// TODO: Re-evaluate possible upstreams. Currently upstream
|
||||||
|
// reevaluation is triggered via received CONNECTIVITY_ACTION
|
||||||
|
// broadcasts that result in being passed a
|
||||||
|
// TetherMasterSM.CMD_UPSTREAM_CHANGED.
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
retValue = false;
|
retValue = false;
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user