Running the Android Emulator in bridge mode

Forgive me Internet, it’s been 18 months since my last blog entry. THIS NO LONGER WORKS

I was sure that I’d blogged this before. The problem: you want to run your Android App connected to an actual WiFi network, where there is mDNS and IPv6, and the like, but the stupid emulator gives you only reverse NAT44’ed networking. Why in 2020, do they still do this? It’s so hostile to making apps work with IPv6.

The emulator is perfectly capable of connecting it’s wifi to a tap device. The “-net-tap” argument is right there! Read the help on it:

obiwan-[~/P](2.6.6) mcr 10082 %/corp/projects/android/Sdk/emulator/emulator -help-net-tap

by default, the emulator uses user mode networking which does address
translation of all network traffic. Use -net-tap <tap interface> to switch
to TAP network mode where Android will use a TAP interface to connect to
the host network directly. Android will attempt to configure the TAP
network using DHCP for IPv4 and SLAAC for IPv6. To be able to access the
network that the host is connected to the TAP interface should be bridged
with another network interface on the host.

<tap interface> is the name of a TAP network interface such as tap0. It
is NOT the path to the TAP device, just the name of the device.

NOTE: Using this disables other options such as net-speed, net-delay,
    -dns-server, -http-proxy, -tcpdump, and -shared-net-id

I did not find a way in the AVD manager to add this argument. (Note interesting “-tcpdump” argument)

The simplest is that you just stop the emulator that is running via the AVD manager. Then start the emulator:

/corp/projects/android/Sdk/emulator/emulator -avd Pixel_API_27 -net-tap 5x &

At this point, the AVD manager doesn’t believe that the emulator is running, but you can easily launch things from the Android studio, and it will work.

Just find the emu-lauch-params.txt in your ~/.android/avd/Pixel_API_27.avd/ (or whatever your image is called), and add:

-net-tap
5x

Where “5x” is the name of the tap device that I have created. Okay, I first made this at a time when the Pixel 5 was current.

If your emulator is running, stop it.

How do you make this tap device, and how to do make sure that your userid can open it?

I do the following in my /etc/network/interfaces.

# LAN behind router
auto lan
iface lan inet manual
    bridge_ports shglan0 5x
   	    pre-up /sandel/bin/tunctl -b -u mcr -t shglan0
    pre-up /sandel/bin/tunctl -b -u mcr -t 5x
    up sysctl -w net.ipv6.conf.lan.accept_ra_defrtr=0
    up sysctl -w net.ipv6.conf.lan.accept_ra=2

You can use tunctl from a number of different places. Historically, I used the one that I had compiled from the user-mode-linux source. You can also use /usr/sbin/vde_tunctl from the vde2 debian package.

You can apparently, also now just do:

pre-up ip tuntap add dev 5x mode tap user mcr

although I haven’t tried this yet.

I make a bridge that is called “lan”, and I create two ports on this. I mark them both as being owned by my userid, “mcr”, and then I change the bridge properties in two ways:

a) I do not accept an IPv6 default route on from that network.
b) I *do* accept the router advertisements from that interface, even though I have IPv6 forwarding enabled on my desktop.

I do (b) so that I can ssh into the router using the IPv6 ULAs that the router emits. You might prefer, instead, to put that entire bridge into it’s own network namespace, in which case your desktop will never directly see it.

On the “shglan0” virtual interface, I happen to run a KVM containing the openwrt image that I wish to debug my android App against. (The app is for controlling the router). That’s pretty specific to me.

Alternatives: bring up a macvlan interface of you eth0, and bridge that so that Android is on your desktop’s LAN.

Or, as I do, I always put my eth0 into a bridge anyway with:

# The primary network interface
auto trusted
iface trusted inet static
	bridge_ports eth0
    address 172.30.2.21
    netmask 255.255.255.0

then I can just pop 5x into the “trusted” interface, if I really want the phone on my trusted LAN. Or, back again to the private LAN.

If you live on a laptop, then you likely don’t want to do static IPs, so change “static” to “dhcp”. Doing the same thing for your wifi probably is better done with some NetworkManager magic, which I don’t know.