2

I creating an Android application that allow to execute some iperf commands. To do that, I got the version 3 of the source code of the IPerf C project and I cross-compile it using those commands :

> make clean
> ./configure --host=arm-linux --prefix=/home/laboPC/Downloads CC=arm-linux-androideabi-gcc CXX=arm-linux-androideabi-g++ CFLAGS="-static" CXXFLAGS="-static" LDFLAGS="-pie -fuse-ld=bfd"
> make

After the cross-compile, I got a binary file that I put in the assets folder in my android project.

For using IPerf from Android, I create a copy of the binary in this way :

private String binariePath = context.getApplicationInfo().dataDir + "/iperf3";

private void setupBinaries(){
     InputStream in = context.getResources().openRawResource(R.raw.iperf3);
     OutputStream out = new FileOutputStream(binariePath);
     byte[] buf = new byte[1024];
     int len;

     while ((len = in.read(buf)) > 0) {
         out.write(buf, 0, len);
     }
     in.close();
     out.flush();
     out.close();
     Runtime.getRuntime().exec("chmod 751 " + binariePath);
}

And then, I using a Runtime object to execute a iperf command like this :

public String runClient (String server, String argument) {
    try {
       setupBinaries();

        process = Runtime.getRuntime().exec(binariePath + " -c " + server + " " + argument);
        BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream()));

        final StringBuilder result = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            result.append(line + "\n");
        }
        reader.close();
        process.destroy();
        return result.toString();

    } catch (IOException e) {
        Log.d("IPERF", e.getLocalizedMessage());
        return e.getLocalizedMessage();
    }
}

Everythings works fine except in Android 7.0. When I runnig my app on the Nexus 5X in Android 7, the iperf command seems not to be execute and my result variable is empty.

I checked that the Runtime.exec() works fine in android 7 and that the binary is correctly copy in the app data directory.

Is everyone has an idea what is wrong in my process ? Is my commands fo compile IPerf project is correct ?

Thanks for your help.

EDIT

I found in the followings threads that Android 6.0 and higher can execute binaries that are compiled with the -fPIC option :

android ndk: are -fPIC and -pie mututally exclusive?

Position Independent Executables and Android Lollipop

So I tried to compile my C project by using this command line :

./configure --host=arm-linux --prefix=/home/laboPC/Downloads CC=arm-linux-androideabi-gcc CXX=arm-linux-androideabi-g++ CFLAGS="-static -fPIC" CXXFLAGS="-static" LDFLAGS="-pie -fuse-ld=bfd"

I think there is something wrong about my command line but I don't know what. Is anybody can help me to identifiate what I wrong in my command line ?

Community
  • 1
  • 1
Red
  • 21
  • 1
  • 3
  • Check your binary directly from device shell: `$ adb push iperf3 /data/local/tmp; adb shell "chmod +x /data/local/tmp/iperf3"; adb shell "/data/local/tmp/iperf3 -c "`. – Sergio Dec 05 '16 at 13:15
  • Thanks for your answer. I do that and I getting a `CANNOT LINK EXECUTABLE "/data/local/tmp/iperf3": /data/local/tmp/iperf3 : has text relocations`. And if I do that on a device other than the Nexus 5X I get a `iperf3: error - unable to create a new stream : Permission denied` – Red Dec 05 '16 at 13:57
  • Try to add `-fpie` to `CFLAGS`, since `-pie` linker option will do the trick only if linked code is position-independent. Also double check that these flags are passed to compiler and linker. – Sergio Dec 05 '16 at 14:09
  • I add the -fpie option like this : `./configure --host=arm-linux --prefix=/home/laboPC/Downloads CC=arm-linux-androideabi-gcc CXX=arm-linux-androideabi-g++ CFLAGS="-static -fpie" CXXFLAGS="-static" LDFLAGS="-pie -fuse-ld=bfd"` and I get a `warrning linker : /data/local/tmp/iperf3 : unsupported flag DT_FLAGS_1=0x8000000. /data/local/tmp/iperf3 : has text relocations` – Red Dec 05 '16 at 15:06

2 Answers2

4

I found your question and it helped me to build iperf3 for Android, but I reached on same problem.
Are you using build toolchains from Ubuntu repository? If yes, built binaries it will not work on Android 7.0, because they are using an old version of build toolchains. You will need to build the binaries with most recent NDK version. (now is r13b)

How I solved it:
-Putted all iperf3 sources from src folder on jni folder
-Created Android.mk and Application.mk, which I'll post below, on same folder, along with other files.
-Inside jni folder, I ran ndk-build and, voila, all binaries on /libs folder, working even on Android 7.0 (pick the binaries, put on assets folder and implement your strategy to load the correct binary for the right abi, or just get armeabi binary and load into your app)

Tip: iperf3 uses an folder to cache the results which is inaccessible for Android. You'll need to change this folder to work:
https://github.com/esnet/iperf/blob/670c18584bcf7a285f3561eb7ea38cc53600d0ab/src/iperf_api.c#L2621

Android.mk: (I think that is not necessary to put .h files on this script)
http://pastebin.com/fPsn0wsD

Application.mk:
http://pastebin.com/sgSsGNqB

I recommend to use ndk-build to build library to make more easier to build iperf3 for different architectures, like x86.

Thiago
  • 661
  • 4
  • 6
  • 1
    I have compiled iperf3 based on your instruction. Could you give guidance to run iperf command using android java page. – Mercy Angel Dec 11 '19 at 12:20
0

If you'll get error:

iperf3: error - unable to create a new stream: Permission denied

Or:

iperf3: error - unable to create a new stream: No such file or directory

You can do what I wrote here: https://stackoverflow.com/a/58578227/12279527