Linkproperties update via unsol data call state change.

Handles the scenario of radio technology handover with IP continuity.
Once RIL/Modem finished a handover operation, an unsol data call state
change will be send up to FW notifying all link propertes changes.
FW will then re-configure the device with new link properties
including iptable used by Tethering.

Change-Id: I05e29f66ac3db8ba4274d3662642607742ba1d12
This commit is contained in:
Kazuhiro Ondo
2011-04-30 20:10:57 -05:00
committed by Wink Saville
parent 258208a78c
commit 01758e81b3
7 changed files with 164 additions and 22 deletions

View File

@ -276,6 +276,21 @@ public class MobileDataStateTracker implements NetworkStateTracker {
setDetailedState(DetailedState.CONNECTED, reason, apnName);
break;
}
} else {
// There was no state change. Check if LinkProperties has been updated.
if (TextUtils.equals(reason, Phone.REASON_LINK_PROPERTIES_CHANGED)) {
mLinkProperties = intent.getParcelableExtra(Phone.DATA_LINK_PROPERTIES_KEY);
if (mLinkProperties == null) {
log("No link property in LINK_PROPERTIES change event.");
mLinkProperties = new LinkProperties();
}
// Just update reason field in this NetworkInfo
mNetworkInfo.setDetailedState(mNetworkInfo.getDetailedState(), reason,
mNetworkInfo.getExtraInfo());
Message msg = mTarget.obtainMessage(EVENT_CONFIGURATION_CHANGED,
mNetworkInfo);
msg.sendToTarget();
}
}
} else if (intent.getAction().
equals(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED)) {

View File

@ -1391,6 +1391,12 @@ public class ConnectivityService extends IConnectivityManager.Stub {
} else {
addPrivateDnsRoutes(mNetTrackers[netType]);
}
/** Notify TetheringService if interface name has been changed. */
if (TextUtils.equals(mNetTrackers[netType].getNetworkInfo().getReason(),
Phone.REASON_LINK_PROPERTIES_CHANGED)) {
handleTetherIfaceChange(netType);
}
} else {
if (mNetConfigs[netType].isDefault()) {
removeDefaultRoute(mNetTrackers[netType]);
@ -2203,6 +2209,14 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
}
private void handleTetherIfaceChange(int type) {
String iface = mNetTrackers[type].getLinkProperties().getInterfaceName();
if (isTetheringSupported()) {
mTethering.handleTetherIfaceChange(iface);
}
}
private void log(String s) {
Slog.d(TAG, s);
}

View File

@ -668,6 +668,16 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
return retVal;
}
public void handleTetherIfaceChange(String iface) {
// check if iface is white listed
for (String regex : mUpstreamIfaceRegexs) {
if (iface.matches(regex)) {
if (DEBUG) Log.d(TAG, "Tethering got Interface Change");
mTetherMasterSM.sendMessage(TetherMasterSM.CMD_IFACE_CHANGED, iface);
break;
}
}
}
class TetherInterfaceSM extends StateMachine {
// notification from the master SM that it's not in tether mode
@ -1076,6 +1086,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
static final int CMD_CELL_CONNECTION_RENEW = 4;
// we don't have a valid upstream conn, check again after a delay
static final int CMD_RETRY_UPSTREAM = 5;
// received an indication that upstream interface has changed
static final int CMD_IFACE_CHANGED = 6;
// This indicates what a timeout event relates to. A state that
// sends itself a delayed timeout event and handles incoming timeout events
@ -1429,13 +1441,18 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
turnOnMobileConnection();
}
break;
case CMD_RETRY_UPSTREAM:
chooseUpstreamType(mTryCell);
mTryCell = !mTryCell;
break;
default:
retValue = false;
break;
case CMD_RETRY_UPSTREAM:
chooseUpstreamType(mTryCell);
mTryCell = !mTryCell;
break;
case CMD_IFACE_CHANGED:
String iface = (String)message.obj;
if (DEBUG) Log.d(TAG, "Activie upstream interface changed: " + iface);
notifyTetheredOfNewUpstreamIface(iface);
break;
default:
retValue = false;
break;
}
return retValue;
}

View File

@ -509,24 +509,58 @@ public abstract class DataConnection extends StateMachine {
result.mFailCause = FailCause.fromInt(response.status);
} else {
log("onSetupConnectionCompleted received DataCallState: " + response);
// Check if system property dns usable
boolean okToUseSystemPropertyDns = false;
cid = response.cid;
String propertyPrefix = "net." + response.ifname + ".";
String dnsServers[] = new String[2];
dnsServers[0] = SystemProperties.get(propertyPrefix + "dns1");
dnsServers[1] = SystemProperties.get(propertyPrefix + "dns2");
okToUseSystemPropertyDns = isDnsOk(dnsServers);
// set link properties based on data call response
result = response.setLinkProperties(mLinkProperties,
okToUseSystemPropertyDns);
isOkToUseSystemPropertyDns(response));
}
return result;
}
private boolean isOkToUseSystemPropertyDns(DataCallState response) {
// Check if system property dns usable
boolean okToUseSystemPropertyDns = false;
String propertyPrefix = "net." + response.ifname + ".";
String dnsServers[] = new String[2];
dnsServers[0] = SystemProperties.get(propertyPrefix + "dns1");
dnsServers[1] = SystemProperties.get(propertyPrefix + "dns2");
okToUseSystemPropertyDns = isDnsOk(dnsServers);
return okToUseSystemPropertyDns;
}
private boolean updateLinkProperty(DataCallState newState) {
boolean changed = false;
if (newState == null) return changed;
DataCallState.SetupResult result;
LinkProperties linkProperties = new LinkProperties();
// set link properties based on data call response
result = newState.setLinkProperties(linkProperties,
isOkToUseSystemPropertyDns(newState));
if (result != DataCallState.SetupResult.SUCCESS) {
log("updateLinkProperty failed : " + result);
return changed;
}
if (mLinkProperties != null) {
// Before comparison, copy HTTP proxy from the original
// as it is not part DataCallState.
linkProperties.setHttpProxy(mLinkProperties.getHttpProxy());
if (!mLinkProperties.equals(linkProperties)) {
mLinkProperties = linkProperties;
changed = true;
}
} else {
mLinkProperties = linkProperties;
changed = true;
}
return changed;
}
/**
* The parent state for all other states.
*/
@ -597,17 +631,24 @@ public abstract class DataConnection extends StateMachine {
mAc.replyToMessage(msg, DataConnectionAc.RSP_SET_LINK_PROPERTIES_HTTP_PROXY);
break;
}
case DataConnectionAc.REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE: {
DataCallState newState = (DataCallState) msg.obj;
int updated = updateLinkProperty(newState) ? 1 : 0;
if (DBG) {
log("REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE updated=" + updated +
" newState=" + newState);
}
mAc.replyToMessage(msg,
DataConnectionAc.RSP_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE,
updated);
break;
}
case DataConnectionAc.REQ_GET_LINK_CAPABILITIES: {
LinkCapabilities lc = new LinkCapabilities(mCapabilities);
log("REQ_GET_LINK_CAPABILITIES linkCapabilities" + lc);
mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_LINK_CAPABILITIES, lc);
break;
}
case DataConnectionAc.REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE: {
Bundle data = msg.getData();
mLinkProperties = (LinkProperties) data.get("linkProperties");
break;
}
case DataConnectionAc.REQ_RESET:
if (DBG) log("DcDefaultState: msg.what=REQ_RESET");
clearSettings();

View File

@ -225,6 +225,38 @@ public class DataConnectionAc extends AsyncChannel {
}
}
/**
* Request update LinkProperties from DataCallState
* Response {@link #rspUpdateLinkPropertiesDataCallState}
*/
public void reqUpdateLinkPropertiesDataCallState(DataCallState newState) {
sendMessage(REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE, newState);
if (DBG) log("reqUpdateLinkPropertiesDataCallState");
}
public boolean rspUpdateLinkPropertiesDataCallState(Message response) {
boolean retVal = response.arg1 == 1;
if (DBG) log("rspUpdateLinkPropertiesState=" + retVal);
return retVal;
}
/**
* Update link properties in the data connection
*
* @return true if link property has been updated. false otherwise.
*/
public boolean updateLinkPropertiesDataCallStateSync(DataCallState newState) {
Message response =
sendMessageSynchronously(REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE, newState);
if ((response != null) &&
(response.what == RSP_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE)) {
return rspUpdateLinkPropertiesDataCallState(response);
} else {
log("getLinkProperties error response=" + response);
return false;
}
}
/**
* Request the connections LinkCapabilities.
* Response {@link #rspLinkCapabilities}

View File

@ -178,6 +178,7 @@ public interface Phone {
static final String REASON_NW_TYPE_CHANGED = "nwTypeChanged";
static final String REASON_DATA_DEPENDENCY_MET = "dependencyMet";
static final String REASON_DATA_DEPENDENCY_UNMET = "dependencyUnmet";
static final String REASON_LINK_PROPERTIES_CHANGED = "linkPropertiesChanged";
// Used for band mode selection methods
static final int BM_UNSPECIFIED = 0; // selected by baseband automatically

View File

@ -987,6 +987,15 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
return false;
}
private DataCallState findDataCallStateByCID (ArrayList<DataCallState> states, int cid) {
for (int i = 0, s = states.size() ; i < s ; i++) {
if (states.get(i).cid == cid) {
return states.get(i);
}
}
return null;
}
/**
* Handles changes to the APN database.
*/
@ -1090,6 +1099,19 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
TelephonyManager.getDefault().getNetworkType());
cleanUpConnection(true, apnContext);
} else {
// Here, data call list has active cid for given ApnContext.
// Check if link property has been updated.
DataCallState state = findDataCallStateByCID(dataCallStates,
apnContext.getDataConnectionAc().getCidSync());
if ((dcac != null) && (state != null)){
if (dcac.updateLinkPropertiesDataCallStateSync(state)) {
// notify data change for this apn
mPhone.notifyDataConnection(Phone.REASON_LINK_PROPERTIES_CHANGED,
apnContext.getApnType());
}
}
}
}
}