Add some tests to ensure BluetoothExceptions are handled

This is just the beginning.

Also fixed a bug that put(null) on the blocking queue, which apparently
is not supported.

Test: TH
Change-Id: I26f6669f483d76fcba83735bb6d32880e23dd451
diff --git a/tests/unit/java/com/android/server/connectivityservice/CSL2capProviderTest.kt b/tests/unit/java/com/android/server/connectivityservice/CSL2capProviderTest.kt
index d44bd0a..4890f4b 100644
--- a/tests/unit/java/com/android/server/connectivityservice/CSL2capProviderTest.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/CSL2capProviderTest.kt
@@ -41,11 +41,14 @@
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
 import com.android.testutils.DevSdkIgnoreRunner
 import com.android.testutils.RecorderCallback.CallbackEntry.Reserved
+import com.android.testutils.RecorderCallback.CallbackEntry.Unavailable
 import com.android.testutils.TestableNetworkCallback
 import java.io.IOException
+import java.util.Optional
 import java.util.concurrent.Executor
 import java.util.concurrent.LinkedBlockingQueue
 import kotlin.test.assertEquals
+import kotlin.test.assertFalse
 import kotlin.test.assertNull
 import org.junit.After
 import org.junit.Before
@@ -54,6 +57,7 @@
 import org.mockito.Mock
 import org.mockito.Mockito.doAnswer
 import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.doThrow
 import org.mockito.Mockito.mock
 import org.mockito.MockitoAnnotations
 
@@ -72,7 +76,10 @@
     private val btServerSocket = mock<BluetoothServerSocket>()
     private val btSocket = mock<BluetoothSocket>()
     private val providerDeps = mock<L2capNetworkProvider.Dependencies>()
-    private val acceptQueue = LinkedBlockingQueue<BluetoothSocket>()
+    // BlockingQueue does not support put(null) operations, as null is used as an internal sentinel
+    // value. Therefore, use Optional<BluetoothSocket> where an empty optional signals the
+    // BluetoothServerSocket#close() operation.
+    private val acceptQueue = LinkedBlockingQueue<Optional<BluetoothSocket>>()
 
     private val handlerThread = HandlerThread("CSL2capProviderTest thread").apply { start() }
 
@@ -87,11 +94,12 @@
 
         doAnswer {
             val sock = acceptQueue.take()
-            sock ?: throw IOException()
+            if (sock == null || !sock.isPresent()) throw IOException()
+            sock.get()
         }.`when`(btServerSocket).accept()
 
         doAnswer {
-            acceptQueue.put(null)
+            acceptQueue.put(Optional.empty())
         }.`when`(btServerSocket).close()
 
         doReturn(handlerThread).`when`(providerDeps).getHandlerThread()
@@ -188,4 +196,42 @@
         nr = REQUEST.copyWithSpecifier(specifier)
         reserveNetwork(nr).assertNoCallback()
     }
+
+    @Test
+    fun testBluetoothException_listenUsingInsecureL2capChannelThrows() {
+        doThrow(IOException()).`when`(btAdapter).listenUsingInsecureL2capChannel()
+        var specifier = L2capNetworkSpecifier.Builder()
+                .setRole(ROLE_SERVER)
+                .setHeaderCompression(HEADER_COMPRESSION_6LOWPAN)
+                .build()
+        var nr = REQUEST.copyWithSpecifier(specifier)
+        reserveNetwork(nr).expect<Unavailable>()
+
+        doReturn(btServerSocket).`when`(btAdapter).listenUsingInsecureL2capChannel()
+        reserveNetwork(nr).expect<Reserved>()
+    }
+
+    @Test
+    fun testBluetoothException_acceptThrows() {
+        doThrow(IOException()).`when`(btServerSocket).accept()
+        var specifier = L2capNetworkSpecifier.Builder()
+                .setRole(ROLE_SERVER)
+                .setHeaderCompression(HEADER_COMPRESSION_6LOWPAN)
+                .build()
+        var nr = REQUEST.copyWithSpecifier(specifier)
+        val cb = reserveNetwork(nr)
+        cb.expect<Reserved>()
+        cb.expect<Unavailable>()
+
+        // BluetoothServerSocket#close() puts Optional.empty() on the acceptQueue.
+        acceptQueue.clear()
+        doAnswer {
+            val sock = acceptQueue.take()
+            assertFalse(sock.isPresent())
+            throw IOException() // to indicate the socket was closed.
+        }.`when`(btServerSocket).accept()
+        val cb2 = reserveNetwork(nr)
+        cb2.expect<Reserved>()
+        cb2.assertNoCallback()
+    }
 }