Skip to content

Conversation

weili-jiang
Copy link
Contributor

Baresip's default networking currently doesn't work well on Android when IPv6-only due to inability to enumerate network interfaces. This appears to be because ifaddrs support is currently disabled. There are APIs to manually add interfaces but this is cumbersome to use.

Android added ifaddrs support in API level 24 (Android 7) which was ages ago:
https://android.googlesource.com/platform/bionic/+/master/libc/include/ifaddrs.h#81

I have enabled it and tested that with this change, Baresip can successfully use getifaddrs on a non-rooted Android 13 phone to enumerate IPv6-only interfaces without any manual steps.

@weili-jiang
Copy link
Contributor Author

weili-jiang commented May 22, 2025

It would appear that the tool chain for the CI is targeting an API version that is < 24, so I have added conditional logic to detect the case where the header exists but isn't available due to targeting the wrong API version. It does mean that the CI will not be building the ifaddrs code for Android. Is there any motivation to up the supported Android API version? Android API 21 is Android 5.0, which is well out of support...

@alfredh
Copy link
Contributor

alfredh commented May 22, 2025

currently the minimum Android version for this project is Android 7.0

https://github.com/baresip/baresip/wiki/Supported-platforms

This version can be adjusted up/down depending on the users

Are you able to also update the CI job with your suggestion version,
and perhaps also add running of the retest program ?

@weili-jiang
Copy link
Contributor Author

The linked page is a bit confusing, the table says Android 5.0+ but the detailed list says 7.0? If it is actually 7.0, yes, I can try update the CI to the equivalent SDK API level (which actually is the required API 24). In which case, should I leave the conditional in if all supported Android versions (i.e. 7.0 or greater) have ifaddrs?

I'm not sure what you mean by adding running of retest. Do you just want me to run retest on x86 against this change or do you want me to do something on Android?

@alfredh
Copy link
Contributor

alfredh commented May 22, 2025

here is part of the Android CI job:

    - name: "build openssl"
      if: steps.openssl.outputs.cache-hit != 'true'
      run: |
        wget -q https://www.openssl.org/source/openssl-$openssl.tar.gz
        tar -xzf openssl-$openssl.tar.gz
        mv openssl-$openssl openssl
        cd openssl && ANDROID_NDK_ROOT=$ANDROID_NDK_LATEST_HOME PATH=$ANDROID_NDK_LATEST_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH ./Configure android-arm64 no-shared no-tests -U__ANDROID_API__ -D__ANDROID_API__=21 && PATH=$ANDROID_NDK_LATEST_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH make build_libs && cd ..

    - name: build
      run: |
        cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_LATEST_HOME/build/cmake/android.toolchain.cmake -DANDROID_ABI="arm64-v8a" -DANDROID_PLATFORM=android-21 -DOPENSSL_ROOT_DIR=openssl -DOPENSSL_INCLUDE_DIR=openssl/include -DOPENSSL_CRYPTO_LIBRARY=openssl/libcrypto.a -DOPENSSL_SSL_LIBRARY=openssl/libssl.a .
        cmake --build . -j 4 -t retest

it would be great if you can update the CI to match the version that you suggested.

I dont think you need to put too much effort into that it works on all Android versions.
If it works on the supported version and later that should be good enough.

An optional step if you have time could be to add execution of retest ...

@weili-jiang weili-jiang force-pushed the android-ifaddrs branch 25 times, most recently from 9e8b407 to d68d291 Compare May 23, 2025 09:13
@alfredh
Copy link
Contributor

alfredh commented May 23, 2025

many thanks for updating the CI.

Let us ask @juha-h for tips and advice. He has an Android application using baresip+libre.
Did you have to use the workarounds mentioned in this diff ?

@juha-h
Copy link
Contributor

juha-h commented May 23, 2025

This is how I learn about available networks in my Android app:

cm = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
        val builder = NetworkRequest.Builder()
            .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
        cm.registerNetworkCallback(
                builder.build(),
                object : ConnectivityManager.NetworkCallback() {

                    override fun onAvailable(network: Network) {
                        super.onAvailable(network)
                        Log.d(TAG, "Network $network is available")
                        if (network !in allNetworks)
                            allNetworks.add(network)
                    }

                    override fun onLosing(network: Network, maxMsToLive: Int) {
                        super.onLosing(network, maxMsToLive)
                        Log.d(TAG, "Network $network is losing after $maxMsToLive ms")
                    }

                    override fun onLost(network: Network) {
                        super.onLost(network)
                        Log.d(TAG, "Network $network is lost")
                        if (network in allNetworks)
                            allNetworks.remove(network)
                        if (isServiceRunning)
                            updateNetwork()
                    }

                    override fun onCapabilitiesChanged(network: Network, caps: NetworkCapabilities) {
                        super.onCapabilitiesChanged(network, caps)
                        Log.d(TAG, "Network $network capabilities changed: $caps")
                        if (network !in allNetworks)
                            allNetworks.add(network)
                        if (isServiceRunning)
                            updateNetwork()
                    }

                    override fun onLinkPropertiesChanged(network: Network, props: LinkProperties) {
                        super.onLinkPropertiesChanged(network, props)
                        Log.d(TAG, "Network $network link properties changed: $props")
                        if (network !in allNetworks)
                            allNetworks.add(network)
                        if (isServiceRunning)
                            updateNetwork()
                    }

                }
        )

So perhaps this PR is not related to my app.

@weili-jiang
Copy link
Contributor Author

weili-jiang commented May 24, 2025

So perhaps this PR is not related to my app.

@juha-h I agree. Yours is the existing way by manually adding interfaces to Baresip via hooks from the Java API. It is the more advanced integration method, and is not related to this MR.

This MR enables the simple way Baresip does itself on other platforms by enumerating interfaces to work on Android too when there is only IPv6. The advanced way is still available and arguably gives better performance, but requires deeper integration with Android in Java, whereas this works out of the box from C.

Are you using C11 threads targetting API >= 30? For me, if I HAVE_THREADS is enabled as it is automatically by cmake when targetting API >= 30 Baresip fails to start due to the rss_set incompatibility between what this library expects and what Bionic implements.

@alfredh I think everything else is only related to retest. The unix socket one is a bit special, technically Android supports it but only if you are using abstract addresses so it can't run in the tests due to inability to set such an address. I didn't see any harm in leaving it on by default as is since it's not critical to Baresip operation unlike HAVE_THREADS. What I think should be done on this is to add support for abstract addresses, and add a separate test case for pathname versus abstract, and only run the abstract test for Android.

@juha-h
Copy link
Contributor

juha-h commented May 24, 2025

@weili-jiang I have in CMakeLists.txt:

add_definitions(-DHAVE_PTHREAD)

My app targets targetSdk = 35 and I have not noticed any issues with starting baresip.

@weili-jiang
Copy link
Contributor Author

weili-jiang commented May 24, 2025

@weili-jiang I have in CMakeLists.txt:

add_definitions(-DHAVE_PTHREAD)

My app targets targetSdk = 35 and I have not noticed any issues with starting baresip.

@juha-h I am also using with HAVE_PTHREAD (pthread.h), but that's not what I was talking about. The issue is with HAVE_THREADS which is different - C11 threads.h. I have to disable HAVE_THREADS so that it uses pthread instead, same as you.

Why are you manually needing to specify HAVE_PTHREAD BTW? Is your re cmake build (using re-config.cmake) not autodetecting the pthreads.h etc from the NDK? In my case it autodetects both threads.h and pthread.h but doesn't realise the first is not compatible.

@juha-h
Copy link
Contributor

juha-h commented May 24, 2025

@weili-jiang I don't remember why I have added add_definitions(-DHAVE_PTHREAD) to baresip app (not re) CMakeLists.txt. When I build re for libbaresip this is what I see in output:

-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - not found
-- Check if compiler accepts -pthread
-- Check if compiler accepts -pthread - yes
-- Found Threads: TRUE  

@juha-h
Copy link
Contributor

juha-h commented May 24, 2025

@weili-jiang I tried without add_definitions(-DHAVE_PTHREAD) and baresip seems to start OK and does not complain when I use pthread, e.g.

int ret = pthread_create(&loggingThread, NULL, loggingFunction, NULL);
    if (ret != 0) {
        LOGE("failed to create logging thread: %d", ret);
        return ret;
    }

I don't know why re build does not find pthread or if it matters.

@weili-jiang
Copy link
Contributor Author

weili-jiang commented May 24, 2025

@juha-h are you building libre yourself as well as Baresip? Do you have this in the log for building libre which would indicate usage of C11 threads?

-- Looking for threads.h
-- Looking for threads.h - found

Also check if src/thread/posix.c.o is in the build logs - that is only built if using pthread instead of C11 threads.

@juha-h
Copy link
Contributor

juha-h commented May 24, 2025

@weili-jiang Yes, I'm building libre and libbaresip myself https://github.com/juha-h/libbaresip-android. Yes, I see this in re build log:

-- Looking for threads.h
-- Looking for threads.h - found

And yes, there is posix.c in the build log:

 Building C object CMakeFiles/re-objs.dir/src/thread/posix.c.o

So I'm really confused when build does not find pthread_create:

-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - not found

and still pthread_create calls works in the app.

@weili-jiang weili-jiang marked this pull request as draft May 24, 2025 16:07
@weili-jiang weili-jiang force-pushed the android-ifaddrs branch 3 times, most recently from 26c1f5e to 7dd0691 Compare May 24, 2025 16:26
@weili-jiang
Copy link
Contributor Author

The test I just added for tss_set seems to be working in the Android emulator so I'll assume it does work, might be something else going wrong in my situation. Do the rest of the changes to retest seem reasonable?

@alfredh
Copy link
Contributor

alfredh commented May 27, 2025

this looks very nice, thanks!

Could you please split up the PR into logical parts so that it does not become so big ?

Also after some thinking I think it is best to use minimum level of 21
and add the checks for getaddrinfo that you had in the first round ...

@weili-jiang
Copy link
Contributor Author

weili-jiang commented May 27, 2025

this looks very nice, thanks!

Could you please split up the PR into logical parts so that it does not become so big ?

Also after some thinking I think it is best to use minimum level of 21 and add the checks for getaddrinfo that you had in the first round ...

@alfredh Just to be clear, how many separate PRs?

  • Fix retest for file I/O on Android
  • Add thread tss test
  • Add Android CI for API 21
  • Add ifaddrs (not tested on Android due to API 21)

Agreed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants