Merge changes I32434588,I61efbedb into main
* changes:
Mark blanket offer as transport primary
Add createL2capNetwork helper
diff --git a/service/src/com/android/server/L2capNetworkProvider.java b/service/src/com/android/server/L2capNetworkProvider.java
index 787cab5..15c860b 100644
--- a/service/src/com/android/server/L2capNetworkProvider.java
+++ b/service/src/com/android/server/L2capNetworkProvider.java
@@ -30,11 +30,15 @@
import static android.net.NetworkCapabilities.RES_ID_MATCH_ALL_RESERVATIONS;
import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
import static android.content.pm.PackageManager.FEATURE_BLUETOOTH_LE;
+import static android.system.OsConstants.F_GETFL;
+import static android.system.OsConstants.F_SETFL;
+import static android.system.OsConstants.O_NONBLOCK;
import android.annotation.Nullable;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothServerSocket;
+import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
@@ -48,10 +52,14 @@
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
+import android.os.ParcelFileDescriptor;
+import android.system.Os;
import android.util.ArraySet;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.net.module.util.ServiceConnectivityJni;
+import com.android.server.net.L2capNetwork;
import java.io.IOException;
import java.util.Set;
@@ -84,6 +92,10 @@
@Nullable
private BluetoothManager mBluetoothManager;
+ // Note: IFNAMSIZ is 16.
+ private static final String TUN_IFNAME = "l2cap-tun";
+ private static int sTunIndex = 0;
+
/**
* The blanket reservation offer is used to create an L2CAP server network, i.e. a network
* based on a BluetoothServerSocket.
@@ -92,10 +104,12 @@
* requests that do not have a NetworkSpecifier set.
*/
private class BlanketReservationOffer implements NetworkOfferCallback {
- // TODO: ensure that once the incoming request is satisfied, the blanket offer does not get
- // unneeded. This means the blanket offer must always outscore the reserved offer. This
- // might require setting the blanket offer as setTransportPrimary().
- public static final NetworkScore SCORE = new NetworkScore.Builder().build();
+ // Set as transport primary to ensure that the BlanketReservationOffer always outscores the
+ // ReservedServerOffer, because as soon as the BlanketReservationOffer receives an
+ // onNetworkUnneeded() callback, it will tear down the associated reserved offer.
+ public static final NetworkScore SCORE = new NetworkScore.Builder()
+ .setTransportPrimary(true)
+ .build();
// Note the missing NET_CAPABILITY_NOT_RESTRICTED marking the network as restricted.
public static final NetworkCapabilities CAPABILITIES;
static {
@@ -222,6 +236,40 @@
mProvider.unregisterNetworkOffer(reservedOffer);
}
+ @Nullable
+ private static ParcelFileDescriptor createTunInterface(String ifname) {
+ final ParcelFileDescriptor fd;
+ try {
+ fd = ParcelFileDescriptor.adoptFd(
+ ServiceConnectivityJni.createTunTap(
+ true /*isTun*/, true /*hasCarrier*/, true /*setIffMulticast*/, ifname));
+ ServiceConnectivityJni.bringUpInterface(ifname);
+ // TODO: consider adding a parameter to createTunTap() (or the Builder that should
+ // be added) to configure i/o blocking.
+ final int flags = Os.fcntlInt(fd.getFileDescriptor(), F_GETFL, 0);
+ Os.fcntlInt(fd.getFileDescriptor(), F_SETFL, flags & ~O_NONBLOCK);
+ } catch (Exception e) {
+ // Note: createTunTap currently throws an IllegalStateException on failure.
+ // TODO: native functions should throw ErrnoException.
+ Log.e(TAG, "Failed to create tun interface", e);
+ return null;
+ }
+ return fd;
+ }
+
+ @Nullable
+ private L2capNetwork createL2capNetwork(BluetoothSocket socket, NetworkCapabilities caps,
+ L2capNetwork.ICallback cb) {
+ final String ifname = TUN_IFNAME + String.valueOf(sTunIndex++);
+ final ParcelFileDescriptor tunFd = createTunInterface(ifname);
+ if (tunFd == null) {
+ return null;
+ }
+
+ return new L2capNetwork(mHandler, mContext, mProvider, ifname, socket, tunFd, caps, cb);
+ }
+
+
private class ReservedServerOffer implements NetworkOfferCallback {
private final NetworkCapabilities mReservedCapabilities;
private final BluetoothServerSocket mServerSocket;