Control the Android WiFi TxPower


I am doing some experiments using Android devices and need to manually set the TxPower of the WiFi.

A brief investigation in the Android API didn't give me any satisfied methods. Thus I am considering using iwconfig or tools alike. The following are what I did.

Compile iwconfig with PIE support

First problem I come upon is that Android (after 4.1) enforces any dynamically linked programs to support PIE (Position Independent Executables). You can find many precompiled version of iwconfig online, but I think most of them are not PIE supported. In short, if it's not PIE supported, Android will give you the following error.

Error: only position independent executables (PIE) are supported

You can check whether a program is compiled with PIE support using readelf. If it gives you DYN, you are good to go. Otherwise with EXEC, you need to recompile.

$ readelf -l iwconfig | grep -i "file type"
Elf file type is DYN (Shared object file)

To compile it with PIE support, you need:

  • Android NDK of your target version.
  • Android SDK of your target version.
  • A rooted Android device (with Android 4.1 or higher).

Then you can either: download the source from this page and compile using the NDK tools, or use the handy scripts by @nvamelichev. I suggest the latter one.

After you cloned his repo,

  1. Modify the config.sh script to incorporate your NDK and SDK version and path.
  2. In the Android.mk script, remove/add tools per your need. For me, I only kept iwconfig.
  3. Add -fPIC to CFLAGS and -pie to LDFLAGS.
  4. Run build.sh and your compiled program will be in the libs folder.
  5. Push the program to your device at /system/xbin/ and chmod to 755.
Control your WiFi

The rest is easy, you can do most old school stuffs with iwconfig. For example, you can control the TxPower by

$ adb root
$ adb shell
$ iwconfig wlan0 txpower 30mW

The following is a test script, it sets the txpower from 10mW to 100mW, with a step size of 10mW.

#!/bin/bash
let power=10
for i in `seq 0 9`; do
    let p=$power+$i*10
    echo "$p mW"
    adb shell iwconfig wlan0 txpower "$p"mW
    adb shell iwconfig wlan0 |grep Tx-Power
    sleep 3
done

echo "reset to 30 mW"
adb shell iwconfig wlan0 txpower 30mW
adb shell iwconfig wlan0 |grep Tx-Power

And the following is its output on my Nexus 5.

10 mW
          Bit Rate=72 Mb/s   Tx-Power=10 dBm
20 mW
          Bit Rate=72 Mb/s   Tx-Power=14 dBm
30 mW
          Bit Rate=72 Mb/s   Tx-Power=15 dBm
40 mW
          Bit Rate=72 Mb/s   Tx-Power=17 dBm
50 mW
          Bit Rate=72 Mb/s   Tx-Power=17 dBm
60 mW
          Bit Rate=72 Mb/s   Tx-Power=18 dBm
70 mW
          Bit Rate=72 Mb/s   Tx-Power=19 dBm
80 mW
          Bit Rate=72 Mb/s   Tx-Power=20 dBm
90 mW
          Bit Rate=72 Mb/s   Tx-Power=20 dBm
100 mW
          Bit Rate=72 Mb/s   Tx-Power=20 dBm
reset to 30 mW
          Bit Rate=72 Mb/s   Tx-Power=15 dBm

You can also use the app WiFi TX Power which has some preset power levels. Notice that it also requires iwconfig.

TL;DR, you can use this precompiled iwconfig to control your android wifi.

By