Use ThreadLeakMonitor for CSL2capProviderTest

This CL introduces ThreadLeakMonitor for CSL2capProviderTest.
ThreadLeakMonitor ignores threads with unique names, so all
L2capNetworkProvider related threads must specify a name.

Test: TH
Change-Id: I7cfcc93ab562a1ada2058d8c73e968a8d0005b1d
diff --git a/service/src/com/android/server/L2capNetworkProvider.java b/service/src/com/android/server/L2capNetworkProvider.java
index 8201c39..f303cdc 100644
--- a/service/src/com/android/server/L2capNetworkProvider.java
+++ b/service/src/com/android/server/L2capNetworkProvider.java
@@ -273,6 +273,7 @@
             private volatile boolean mIsRunning = true;
 
             public AcceptThread(BluetoothServerSocket serverSocket) {
+                super("L2capNetworkProvider-AcceptThread");
                 mServerSocket = serverSocket;
             }
 
@@ -436,6 +437,7 @@
             private volatile boolean mIsAborted = false;
 
             public ConnectThread(L2capNetworkSpecifier specifier, BluetoothSocket socket) {
+                super("L2capNetworkProvider-ConnectThread");
                 mSpecifier = specifier;
                 mSocket = socket;
             }
diff --git a/service/src/com/android/server/net/L2capPacketForwarder.java b/service/src/com/android/server/net/L2capPacketForwarder.java
index 00faecf..737cb9c 100644
--- a/service/src/com/android/server/net/L2capPacketForwarder.java
+++ b/service/src/com/android/server/net/L2capPacketForwarder.java
@@ -233,6 +233,7 @@
 
         L2capThread(IReadWriteFd readFd, IReadWriteFd writeFd, boolean isIngress,
                 boolean compressHeaders) {
+            super("L2capNetworkProvider-ForwarderThread");
             mLogTag = isIngress ? "L2capForwarderThread-Ingress" : "L2capForwarderThread-Egress";
             mReadFd = readFd;
             mWriteFd = writeFd;
diff --git a/tests/unit/java/com/android/server/connectivityservice/CSL2capProviderTest.kt b/tests/unit/java/com/android/server/connectivityservice/CSL2capProviderTest.kt
index 4890f4b..7f4744b 100644
--- a/tests/unit/java/com/android/server/connectivityservice/CSL2capProviderTest.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/CSL2capProviderTest.kt
@@ -43,6 +43,7 @@
 import com.android.testutils.RecorderCallback.CallbackEntry.Reserved
 import com.android.testutils.RecorderCallback.CallbackEntry.Unavailable
 import com.android.testutils.TestableNetworkCallback
+import com.android.testutils.waitForIdle
 import java.io.IOException
 import java.util.Optional
 import java.util.concurrent.Executor
@@ -71,6 +72,7 @@
 
 @RunWith(DevSdkIgnoreRunner::class)
 @IgnoreUpTo(Build.VERSION_CODES.R)
+@DevSdkIgnoreRunner.MonitorThreadLeak
 class CSL2capProviderTest : CSTest() {
     private val btAdapter = mock<BluetoothAdapter>()
     private val btServerSocket = mock<BluetoothServerSocket>()
@@ -82,6 +84,7 @@
     private val acceptQueue = LinkedBlockingQueue<Optional<BluetoothSocket>>()
 
     private val handlerThread = HandlerThread("CSL2capProviderTest thread").apply { start() }
+    private val registeredCallbacks = ArrayList<TestableNetworkCallback>()
 
     // Requires Dependencies mock to be setup before creation.
     private lateinit var provider: L2capNetworkProvider
@@ -109,16 +112,30 @@
 
     @After
     fun innerTearDown() {
+        // Unregistering a callback which has previously been unregistered by virtue of receiving
+        // onUnavailable is a noop.
+        registeredCallbacks.forEach { cm.unregisterNetworkCallback(it) }
+        // Wait for CS handler idle, meaning the unregisterNetworkCallback has been processed and
+        // L2capNetworkProvider has been notified.
+        waitForIdle()
+
+        // While quitSafely() effectively waits for idle, it is not enough, because the tear down
+        // path itself posts on the handler thread. This means that waitForIdle() needs to run
+        // twice. The first time, to ensure all active threads have been joined, and the second time
+        // to run all associated clean up actions.
+        handlerThread.waitForIdle(HANDLER_TIMEOUT_MS)
         handlerThread.quitSafely()
         handlerThread.join()
     }
 
     private fun reserveNetwork(nr: NetworkRequest) = TestableNetworkCallback().also {
         cm.reserveNetwork(nr, csHandler, it)
+        registeredCallbacks.add(it)
     }
 
     private fun requestNetwork(nr: NetworkRequest) = TestableNetworkCallback().also {
         cm.requestNetwork(nr, it, csHandler)
+        registeredCallbacks.add(it)
     }
 
     private fun NetworkRequest.copyWithSpecifier(specifier: NetworkSpecifier): NetworkRequest {