Apply a workaround, and try to detect a system crash
This will prevent the system crash in b/194394697, and on T try to
detect the issue much earlier and crash the system at that time
together with much more expansive logs.
Bug: 194394697
Test: ConnectivityServiceTest
Change-Id: Ia4be82179160216d41bf4d88b896e4814385063a
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 6c2f7ee..3bda264 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -229,6 +229,7 @@
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.MessageUtils;
import com.android.modules.utils.BasicShellCommandHandler;
+import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.LinkPropertiesUtils.CompareOrUpdateResult;
@@ -259,6 +260,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.io.Writer;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
@@ -273,6 +275,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
import java.util.SortedSet;
@@ -3193,6 +3196,22 @@
}
}
+ private void dumpAllRequestInfoLogsToLogcat() {
+ try (PrintWriter logPw = new PrintWriter(new Writer() {
+ @Override
+ public void write(final char[] cbuf, final int off, final int len) {
+ // This method is called with 0-length and 1-length arrays for empty strings
+ // or strings containing only the DEL character.
+ if (len <= 1) return;
+ Log.e(TAG, new String(cbuf, off, len));
+ }
+ @Override public void flush() {}
+ @Override public void close() {}
+ })) {
+ mNetworkRequestInfoLogs.dump(logPw);
+ }
+ }
+
/**
* Return an array of all current NetworkAgentInfos sorted by network id.
*/
@@ -4021,6 +4040,19 @@
return null;
}
+ private void checkNrisConsistency(final NetworkRequestInfo nri) {
+ if (SdkLevel.isAtLeastT()) {
+ for (final NetworkRequestInfo n : mNetworkRequests.values()) {
+ if (n.mBinder != null && n.mBinder == nri.mBinder) {
+ // Temporary help to debug b/194394697 ; TODO : remove this function when the
+ // bug is fixed.
+ dumpAllRequestInfoLogsToLogcat();
+ throw new IllegalStateException("This NRI is already registered. " + nri);
+ }
+ }
+ }
+ }
+
private void handleRegisterNetworkRequestWithIntent(@NonNull final Message msg) {
final NetworkRequestInfo nri = (NetworkRequestInfo) (msg.obj);
// handleRegisterNetworkRequestWithIntent() doesn't apply to multilayer requests.
@@ -4046,6 +4078,7 @@
ensureRunningOnConnectivityServiceThread();
for (final NetworkRequestInfo nri : nris) {
mNetworkRequestInfoLogs.log("REGISTER " + nri);
+ checkNrisConsistency(nri);
for (final NetworkRequest req : nri.mRequests) {
mNetworkRequests.put(req, nri);
// TODO: Consider update signal strength for other types.
@@ -4282,6 +4315,7 @@
}
nri.decrementRequestCount();
mNetworkRequestInfoLogs.log("RELEASE " + nri);
+ checkNrisConsistency(nri);
if (null != nri.getActiveRequest()) {
if (!nri.getActiveRequest().isListen()) {
@@ -5919,7 +5953,12 @@
void unlinkDeathRecipient() {
if (null != mBinder) {
- mBinder.unlinkToDeath(this, 0);
+ try {
+ mBinder.unlinkToDeath(this, 0);
+ } catch (NoSuchElementException e) {
+ // Temporary workaround for b/194394697 pending analysis of additional logs
+ Log.wtf(TAG, "unlinkToDeath for already unlinked NRI " + this);
+ }
}
}
@@ -5939,7 +5978,7 @@
@Override
public void binderDied() {
log("ConnectivityService NetworkRequestInfo binderDied(" +
- "uid/pid:" + mUid + "/" + mPid + ", " + mBinder + ")");
+ "uid/pid:" + mUid + "/" + mPid + ", " + mRequests + ", " + mBinder + ")");
// As an immutable collection, mRequests cannot change by the time the
// lambda is evaluated on the handler thread so calling .get() from a binder thread
// is acceptable. Use handleReleaseNetworkRequest and not directly