L2capNetworkProvider should use its own handler thread

Eventually, this will be started by CS, but it should not reuse the CS
handler thread.

Test: TH
Change-Id: I20dc252d91351cf92724d640e272f28ddc29dbf4
diff --git a/service/src/com/android/server/L2capNetworkProvider.java b/service/src/com/android/server/L2capNetworkProvider.java
index a2d4347..c5ec9ee 100644
--- a/service/src/com/android/server/L2capNetworkProvider.java
+++ b/service/src/com/android/server/L2capNetworkProvider.java
@@ -33,6 +33,7 @@
 
 import android.annotation.Nullable;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.net.ConnectivityManager;
 import android.net.L2capNetworkSpecifier;
 import android.net.NetworkCapabilities;
@@ -42,6 +43,7 @@
 import android.net.NetworkScore;
 import android.net.NetworkSpecifier;
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.Looper;
 import android.util.ArrayMap;
 import android.util.Log;
@@ -54,6 +56,8 @@
 public class L2capNetworkProvider {
     private static final String TAG = L2capNetworkProvider.class.getSimpleName();
     private final Dependencies mDeps;
+    private final Context mContext;
+    private final HandlerThread mHandlerThread;
     private final Handler mHandler;
     private final NetworkProvider mProvider;
     private final BlanketReservationOffer mBlanketOffer;
@@ -201,26 +205,40 @@
         public NetworkProvider getNetworkProvider(Context context, Looper looper) {
             return new NetworkProvider(context, looper, TAG);
         }
+
+        /** Get the HandlerThread for L2capNetworkProvider to run on */
+        public HandlerThread getHandlerThread() {
+            final HandlerThread thread = new HandlerThread("L2capNetworkProviderThread");
+            thread.start();
+            return thread;
+        }
     }
 
-    public L2capNetworkProvider(Context context, Handler handler) {
-        this(new Dependencies(), context, handler);
+    public L2capNetworkProvider(Context context) {
+        this(new Dependencies(), context);
     }
 
     @VisibleForTesting
-    public L2capNetworkProvider(Dependencies deps, Context context, Handler handler) {
+    public L2capNetworkProvider(Dependencies deps, Context context) {
         mDeps = deps;
-        mHandler = handler;
-        mProvider = mDeps.getNetworkProvider(context, handler.getLooper());
+        mContext = context;
+        mHandlerThread = mDeps.getHandlerThread();
+        mHandler = new Handler(mHandlerThread.getLooper());
+        mProvider = mDeps.getNetworkProvider(context, mHandlerThread.getLooper());
         mBlanketOffer = new BlanketReservationOffer();
+    }
 
-        final boolean isBleSupported =
-                context.getPackageManager().hasSystemFeature(FEATURE_BLUETOOTH_LE);
-        if (isBleSupported) {
-            context.getSystemService(ConnectivityManager.class).registerNetworkProvider(mProvider);
+    /**
+     * Start L2capNetworkProvider.
+     *
+     * Called on CS Handler thread.
+     */
+    public void start() {
+        final PackageManager pm = mContext.getPackageManager();
+        if (pm.hasSystemFeature(FEATURE_BLUETOOTH_LE)) {
+            mContext.getSystemService(ConnectivityManager.class).registerNetworkProvider(mProvider);
             mProvider.registerNetworkOffer(BlanketReservationOffer.SCORE,
                     BlanketReservationOffer.CAPABILITIES, mHandler::post, mBlanketOffer);
         }
     }
 }
-
diff --git a/tests/unit/java/com/android/server/L2capNetworkProviderTest.kt b/tests/unit/java/com/android/server/L2capNetworkProviderTest.kt
index ffa9828..5a7515e 100644
--- a/tests/unit/java/com/android/server/L2capNetworkProviderTest.kt
+++ b/tests/unit/java/com/android/server/L2capNetworkProviderTest.kt
@@ -81,6 +81,7 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
         doReturn(provider).`when`(deps).getNetworkProvider(any(), any())
+        doReturn(handlerThread).`when`(deps).getHandlerThread()
         doReturn(cm).`when`(context).getSystemService(eq(ConnectivityManager::class.java))
         doReturn(pm).`when`(context).getPackageManager()
         doReturn(true).`when`(pm).hasSystemFeature(FEATURE_BLUETOOTH_LE)
@@ -94,7 +95,7 @@
 
     @Test
     fun testNetworkProvider_registeredWhenSupported() {
-        L2capNetworkProvider(deps, context, handler)
+        L2capNetworkProvider(deps, context).start()
         verify(cm).registerNetworkProvider(eq(provider))
         verify(provider).registerNetworkOffer(any(), any(), any(), any())
     }
@@ -102,13 +103,13 @@
     @Test
     fun testNetworkProvider_notRegisteredWhenNotSupported() {
         doReturn(false).`when`(pm).hasSystemFeature(FEATURE_BLUETOOTH_LE)
-        L2capNetworkProvider(deps, context, handler)
+        L2capNetworkProvider(deps, context).start()
         verify(cm, never()).registerNetworkProvider(eq(provider))
     }
 
     fun doTestBlanketOfferIgnoresRequest(request: NetworkRequest) {
         clearInvocations(provider)
-        L2capNetworkProvider(deps, context, handler)
+        L2capNetworkProvider(deps, context).start()
 
         val blanketOfferCaptor = ArgumentCaptor.forClass(NetworkOfferCallback::class.java)
         verify(provider).registerNetworkOffer(any(), any(), any(), blanketOfferCaptor.capture())
@@ -122,7 +123,7 @@
             reservation: NetworkCapabilities
     ) {
         clearInvocations(provider)
-        L2capNetworkProvider(deps, context, handler)
+        L2capNetworkProvider(deps, context).start()
 
         val blanketOfferCaptor = ArgumentCaptor.forClass(NetworkOfferCallback::class.java)
         verify(provider).registerNetworkOffer(any(), any(), any(), blanketOfferCaptor.capture())