Merge "Fixed dangling network agent issue"
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index 05bd3e5..78f7779 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -59,6 +59,7 @@
import android.telephony.data.DataService;
import android.telephony.data.DataServiceCallback;
import android.text.TextUtils;
+import android.util.LocalLog;
import android.util.Pair;
import android.util.StatsLog;
import android.util.TimeUtils;
@@ -178,6 +179,8 @@
private final String mTagSuffix;
+ private final LocalLog mHandoverLocalLog = new LocalLog(100);
+
/**
* Used internally for saving connecting parameters.
*/
@@ -684,6 +687,7 @@
linkProperties = dc.getLinkProperties();
// Preserve the potential network agent from the source data connection. The ownership
// is not transferred at this moment.
+ mHandoverLocalLog.log("Handover started. Preserved the agent.");
mHandoverSourceNetworkAgent = dc.getNetworkAgent();
log("Get the handover source network agent: " + mHandoverSourceNetworkAgent);
dc.setHandoverState(HANDOVER_STATE_BEING_TRANSFERRED);
@@ -1685,6 +1689,31 @@
mHandoverState = HANDOVER_STATE_COMPLETED;
}
+ // Check for dangling agent. Ideally the handover source agent should be null if
+ // handover process is smooth. When it's not null, that means handover failed. The
+ // agent was not successfully transferred to the new data connection. We should
+ // gracefully notify connectivity service the network was disconnected.
+ if (mHandoverSourceNetworkAgent != null) {
+ DataConnection sourceDc = mHandoverSourceNetworkAgent.getDataConnection();
+ if (sourceDc != null) {
+ // If the source data connection still owns this agent, then just reset the
+ // handover state back to idle because handover is already failed.
+ mHandoverLocalLog.log(
+ "Handover failed. Reset the source dc state to idle");
+ sourceDc.setHandoverState(HANDOVER_STATE_IDLE);
+ } else {
+ // The agent is now a dangling agent. No data connection owns this agent.
+ // Gracefully notify connectivity service disconnected.
+ mHandoverLocalLog.log(
+ "Handover failed and dangling agent found.");
+ mHandoverSourceNetworkAgent.acquireOwnership(
+ DataConnection.this, mTransportType);
+ mHandoverSourceNetworkAgent.sendNetworkInfo(mNetworkInfo, DataConnection.this);
+ mHandoverSourceNetworkAgent.releaseOwnership(DataConnection.this);
+ }
+ mHandoverSourceNetworkAgent = null;
+ }
+
if (mConnectionParams != null) {
if (DBG) {
log("DcInactiveState: enter notifyConnectCompleted +ALL failCause="
@@ -1959,7 +1988,9 @@
}
if (mHandoverSourceNetworkAgent != null) {
- log("Transfer network agent successfully.");
+ String logStr = "Transfer network agent successfully.";
+ log(logStr);
+ mHandoverLocalLog.log(logStr);
mNetworkAgent = mHandoverSourceNetworkAgent;
mNetworkAgent.acquireOwnership(DataConnection.this, mTransportType);
@@ -1973,7 +2004,9 @@
mNetworkAgent.sendLinkProperties(mLinkProperties, DataConnection.this);
mHandoverSourceNetworkAgent = null;
} else {
- loge("Failed to get network agent from original data connection");
+ String logStr = "Failed to get network agent from original data connection";
+ loge(logStr);
+ mHandoverLocalLog.log(logStr);
return;
}
} else {
@@ -2589,6 +2622,8 @@
}
void setHandoverState(@HandoverState int state) {
+ mHandoverLocalLog.log("State changed from " + handoverStateToString(mHandoverState)
+ + " to " + handoverStateToString(state));
mHandoverState = state;
}
@@ -2812,6 +2847,15 @@
return score;
}
+ private String handoverStateToString(@HandoverState int state) {
+ switch (state) {
+ case HANDOVER_STATE_IDLE: return "IDLE";
+ case HANDOVER_STATE_BEING_TRANSFERRED: return "BEING_TRANSFERRED";
+ case HANDOVER_STATE_COMPLETED: return "COMPLETED";
+ default: return "UNKNOWN";
+ }
+ }
+
/**
* Dump the current state.
*
@@ -2841,7 +2885,7 @@
pw.println("mLinkProperties=" + mLinkProperties);
pw.flush();
pw.println("mDataRegState=" + mDataRegState);
- pw.println("mHandoverState=" + mHandoverState);
+ pw.println("mHandoverState=" + handoverStateToString(mHandoverState));
pw.println("mRilRat=" + mRilRat);
pw.println("mNetworkCapabilities=" + getNetworkCapabilities());
pw.println("mCreateTime=" + TimeUtils.logTimeOfDay(mCreateTime));
@@ -2859,6 +2903,10 @@
if (mNetworkAgent != null) {
mNetworkAgent.dump(fd, pw, args);
}
+ pw.println("handover local log:");
+ pw.increaseIndent();
+ mHandoverLocalLog.dump(fd, pw, args);
+ pw.decreaseIndent();
pw.decreaseIndent();
pw.println();
pw.flush();
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java b/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java
index b36a490..d9edd28 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java
@@ -132,6 +132,13 @@
mDataConnection = null;
}
+ /**
+ * @return The data connection that owns this agent
+ */
+ public synchronized DataConnection getDataConnection() {
+ return mDataConnection;
+ }
+
@Override
protected synchronized void unwanted() {
if (mDataConnection == null) {