Access android devices from LXC

11 Feb 2016
Posted by stylesen

LXC aka Linux Containers are a convenient way to run a light weight Virtual Machine. LXC provides a complete operating system with access to devices attached to host machine. Let us see how we can access an Android device from a LXC instance via adb or fastboot. I assume you have a working LXC with networking setup properly. I am using a LXC named 'test-lxc' which is a Debian sid based container (root@test-lxc:/#) and a Google Nexus 4 as android device with debug mode enabled. My host machine (stylesen@harshu:~$) is a Debian sid based Thinkpad. When I plug in the USB cable from the android device to my host machine I could see the following in the lsusb output:

stylesen@harshu:~$ lsusb
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 007: ID 04f2:b217 Chicony Electronics Co., Ltd Lenovo Integrated Camera (0.3MP)
Bus 001 Device 005: ID 147e:2016 Upek Biometric Touchchip/Touchstrip Fingerprint Sensor
Bus 001 Device 021: ID 18d1:4ee0 Google Inc.
Bus 001 Device 008: ID 0835:1601 Action Star Enterprise Co., Ltd
Bus 001 Device 003: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

From the above we can see my Nexus 4 (Google Inc.) is connected in USB bus 001 as device 021. The actual path of the Nexus 4 device translates to the following:

/dev/bus/usb/001/021

Within my LXC, though the Nexus 4 appears in lsusb output as follows, adb or fastboot does not have access to this device yet:

root@test-lxc:/# lsusb
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 007: ID 04f2:b217 Chicony Electronics Co., Ltd Lenovo Integrated Camera (0.3MP)
Bus 001 Device 005: ID 147e:2016 Upek Biometric Touchchip/Touchstrip Fingerprint Sensor
Bus 001 Device 021: ID 18d1:4ee0 Google Inc.
Bus 001 Device 008: ID 0835:1601 Action Star Enterprise Co., Ltd
Bus 001 Device 003: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Both fastboot and adb cannot see the device as shown below:

root@test-lxc:/# fastboot devices
root@test-lxc:/# adb devices
List of devices attached

root@test-lxc:/#

In order to make this device accessible from within the container, use the following command on the host machine:

stylesen@harshu:~$ sudo lxc-device -n test-lxc add /dev/bus/usb/001/021

Once the above command is run, we can access the Nexus 4 via fastboot or adb as follows:

root@test-lxc:/# fastboot devices
04f228d1d9c76f39    fastboot
root@test-lxc:/# fastboot reboot
rebooting...

finished. total time: 3.011s
root@test-lxc:/#

Every time the Nexus 4 is disconnected from USB port and reconnected which also includes a 'reboot' or 'reboot-bootloader', the device number within the USB bus changes, though the bus number remains the same. For example, for every reboot or disconnection the device path will become something like the following:

after reboot:  /dev/bus/usb/001/022

after reboot:  /dev/bus/usb/001/023

...

after reboot: /dev/bus/usb/001/0NN

With the above it is difficult to automate things and also every time you must see output of lsusb to identify the device number and add it to the container with lxc-device command. To make things simple and definite, I have the following udev rule in /etc/udev/rules.d/51-android.rules

SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4ee2", ATTRS{serial}=="04f228d1d9c76f39", MODE="0666", GROUP="plugdev", SYMLINK+="android-nexus4"

Note ATTRS{serial} and SYMLINK+="android-nexus4" which can help us to identify and create a symlink to the Nexus 4 device consitently without worrying about the USB device number on the bus. With the above in place we get a device as follows:

stylesen@harshu:~$ ls -alh /dev/android-nexus4
lrwxrwxrwx 1 root root 15 Feb 11 11:36 /dev/android-nexus4 -> bus/usb/001/022

Now things should be simple to add the above android device to the container with the following command:

stylesen@harshu:~$ sudo lxc-device -n test-lxc add $(sudo readlink -f /dev/android-nexus4)

Within the the container we can access the Nexus 4 via adb as follows:

root@test-lxc:/# adb devices
List of devices attached
04f228d1d9c76f39    device

NOTE1: lsusb is a command which is available via usbutils package in Debian.

NOTE2: When accessing a device within a LXC container via adb, make sure the host's adb daemon is down.