Disclaimer: only do this if you have nothing better to do.

AmbientTalk

While this method is generic to get two Android emulators on the same bridge interface with different IP addresses, I am doing this (currently) in context of AmbientTalk.

Android emulator networks

A standard Android emulator is ran in QEMU, and is in its own cozy network, and has the IP address 10.0.2.15, with default gateway 10.0.2.2. Two Android emulators will not be on the same network, and thus have no direct path of communication.

To account for that, we need to:

  • put both emulators on the same bridge network on the host;
  • somehow manage to get both emulators to accept a TAP device instead of their cozy own user router;
  • change the hardware (MAC) address, and IP address.

The last one is the most hacky one. But don’t be afraid, getting them on a TAP device is also very sketchy!

Let’s do this

First another disclaimer: don’t go bother with a DHCP server. It will only help you get more paracetamol, because you’ll also need to mess with the routing on the Android device.

Create two taps and a bridge

Create two TAP’s that can be accessed by the emulator.

ip tuntap add dev tap0 mode tap user $(whoami)
ip tuntap add dev tap1 mode tap user $(whoami)

Now create a bridge, add both taps.

ip link add bridge0 type bridge
ip link set tap0 master bridge0
ip link set tap1 master bridge0
ip link set bridge0 up
ip link set tap0 up
ip link set tap1 up

Assign yourself 10.0.2.2, enable forwarding across the bridge.

ip addr add 10.0.2.2/24 dev bridge0
sysctl -w net.ipv4.ip_forward=1

Android emulators on a tap

Now create two Android emulators. Mine are called Android and Android2. Something like

avdmanager create avd -n 'Android' -k 'system-images;android-23;default;x86_64'
avdmanager create avd -n 'Android2' -k 'system-images;android-23;default;x86_64'

should take care of that. But at this point, if you’re reading this, you probably have them already.

Getting them bound to the tap device is suprisingly easy, but undocumented. At this point, you might want to start Wireshark on bridge0, to watch how far you get.

emulator @Android -net-tap tap0
emulator @Android2 -net-tap tap1

Messing with IP and MAC

Now both devices will be on your bridge, and you’ll have both an IP address conflict and a MAC address conflict. As far as I can tell, you cannot change that on the emulator commandline.

We’ll leave the first emulator be; but every extra one, you’ll have to change the IP.

The first part is still straightforward. Use adb -s INSTANCE shell to get into your emulator, and su to become root. If you want to know you emulator name, check adb-devices, should be something like emulator-5554.

ifconfig eth0 down
ifconfig eth0 hw ether 52:54:00:12:34:57
ifconfig eth0 up
ip addr del 10.0.2.15/24 brd 10.0.2.255 dev eth0
ip addr add 10.0.2.16/24 brd 10.0.2.255 dev eth0
ip rule add from all lookup main pref 99 # override route lookup for the Android system

Note that 52:54:00:12:34:57 is one above the previous one, you’ll want to increase both for every AVD you need.

Also, kind reminder to turn off your firewall, or to set it to allow broadcasting on the bridge.

Now comes the trick:

In your emulator, go to Settings -> More -> Cellular Networks -> Access Point Names, and add a random one. Apparently, somehow, this triggers the Android OS into accepting the new IP configuration.

It looks like just disabling and re-enabling your Cell connection also works.


Let me know on android-p2p AT rubdos DOT be if I forgot something, or if it didn’t work for you, because I probably did forget something. Happy coding!