juha-h / baresip-studio

baresip library based SIP client for Android
BSD 3-Clause "New" or "Revised" License
274 stars 70 forks source link

Start baresip when switching users (and also allow it in the background) #489

Closed realPyR3X closed 1 month ago

realPyR3X commented 1 month ago

I run GrapheneOS and use multiple users to separate applications. My default user has baresip installed and the box checked to launch at boot. However, when I switch to another user, baresip will disconnect. Upon loading the default user again baresip does not restart and forces me to relaunch the application to re-register. I have a few questions. I also noticed the "Battery optimizations" check box is checked despite this app being fully allowed to work in the background and ignore battery optimizations.

juha-h commented 1 month ago

"baresip will disconnect" Do you mean that baresip app stops running? If so, why? Try to find out by https://github.com/juha-h/baresip-studio/wiki/Debugging.

Even when app is allowed to work in the background, Android may still try to reduce its battery usage for example by restricting app's access to network or enter the app to standby state.

juha-h commented 1 month ago

I tested switching users on Pixel 7 emulator (my Samsung device does not support multiple users). This is what I got to log when baresip was running and I switched to another user:

2024-07-21 20:05:53.373 17089-17089 Baresip                 com.tutpro.baresip                   D  Main onPause
2024-07-21 20:05:54.093 17089-17089 Baresip                 com.tutpro.baresip                   D  Main onStop
---------------------------- PROCESS ENDED (17089) for package com.tutpro.baresip ----------------------------

I searched, but didn't find how to prevent that or if it is possible to prevent at all.

Edit: the process must be ended after switching to another user. The question is, how can switching back be detected so that baresip can be automatically restarted.

juha-h commented 1 month ago

Document https://developer.android.com/develop/background-work/background-tasks/broadcasts/broadcast-exceptions has this:

"Apps that target the API level 26 or higher can't register broadcast receivers for implicit broadcasts in their manifest unless the broadcast is sent specifically to them. However, several broadcasts are exempted from these limitations."

Unfortunately ACTION_USER_BACKGROUND and ACTION_USER_FOREGROUND are not exempted. So when baresip process is ended when which to another user happens, baresip cannot register a receiver in the manifest that would get baresip process re-started when switching back to baresip user happens.

I tried and registered the receiver in baresip service. Its onReceive function was called when baresip user was switched off, but was not called when baresip user was switched back on.

So unless someone proves otherwise, re-starting baresip automatically at user switch is not possible in Android OS. Perhaps GrapheneOS is different and does allow registering user switch receiver in the manifest, but I don't have resources to support that OS.

realPyR3X commented 1 month ago

@juha-h I have several apps that display they are currently running in the background when I come back from a user switch. Some of them include "WG Tunnel" and "Nextcloud Services". In total I have 6 Apps that show in the background before switch and only 5 upon return. The one that closes is baresip. It sends me a notification on the other profile (I can't read it but I assume it's that it closed)

Here is the manifest for WG Tunnel - https://github.com/zaneschepke/wgtunnel/blob/main/app/src/main/AndroidManifest.xml

They seem to be using the exemption. Are you saying that they are not running on the latest API and that is why it works?

realPyR3X commented 1 month ago

It seems it probably works because it's a VPN app. However, can you declare ROLE_EMERGENCY? I.e. to make a call 911 ;)

realPyR3X commented 1 month ago

https://developer.android.com/about/versions/14/changes/fgs-types-required#system-exempted

juha-h commented 1 month ago

It does not make sense that baresip started by a user keeps on running in the background when switch to another another user has happened. For example, when call comes in, it must be for the currently active user.

So Android does is correctly when stops baresip at user switch. When switch back to the baresip user takes place, baresip should get re-started, but it cannot be done, because Android does not allow ACTION_USER_FOREGROUND in AndroidManifest intent filter. I checked and no app available in GitHub has ACTION_USER_FOREGROUND in AndroidManifest.

@realPyR3X Regarding WG Tunnel, can it switch automatically to different, user specific VPN tunnel at user switch?

realPyR3X commented 1 month ago

@juha-h Did you look at the links I gave you? This shows how to use systemExempted to allow baresip to persist in the foreground to avoid the ACTION_USER_FOREGROUND problem.

Yes. I have WG Tunnel running in one profile. When I switch to the other profile it is off, when I switch back it comes back on. This same functionality can be in baresip, but you would have be. You need to declare https://developer.android.com/reference/android/Manifest.permission#FOREGROUND_SERVICE_SYSTEM_EXEMPTED my previous comment was perhaps using ROLE_EMERGENCY since technically baresip could make 911 calls and as a phone app that seems to make sense. You then set android:foregroundServiceType="systemExempted" as in the AndroidManifest.xml I pasted above.

I actually use baresip as my default phone app. A separate issue would be allowing it to persist and be active across profiles (but that is a different issue)

juha-h commented 1 month ago

I don't want baresip of one user to keep on running after switch to another user. After the switch, baresip of old user needs to stopped and baresip of the new user needs to get started if it was running when that user was switched off or if that user has not been active before and that user's baresip has Start Automatically turned on.

I don't understand how FOREGROUND_SERVICE_SYSTEM_EXEMPTED would help to achieve what I described.

juha-h commented 1 month ago

Running baresip in the emulator is too slow on my laptop. Try with this https://box.tutpro.com/tmp/baresip.apk (backup first). It has in manifest:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
...
        <service
            android:name=".BaresipService"
            android:enabled="true"
            android:foregroundServiceType="microphone|phoneCall|systemExempted"
            android:permission="android.permission.FOREGROUND_SERVICE"
            android:persistent="true"
            android:stopWithTask="false" >
        </service>
realPyR3X commented 1 month ago

@juha-h Testing this apk, the app now persists in the background between profiles, however, it does not re-register (i.e. the bubbles do not go green unless the app is put back in focus). Did you pass the https://developer.android.com/reference/android/content/pm/ServiceInfo#FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED to startForeground?

juha-h commented 1 month ago

@realPyR3X I didn't pass FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED, but now I did:

                startForeground(
                    STATUS_NOTIFICATION_ID, snb.build(),
                    if (VERSION.SDK_INT >= 34)
                        FOREGROUND_SERVICE_TYPE_PHONE_CALL or FOREGROUND_SERVICE_TYPE_MICROPHONE or
                                FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED
                    else if (VERSION.SDK_INT >= 30)
                        FOREGROUND_SERVICE_TYPE_PHONE_CALL or FOREGROUND_SERVICE_TYPE_MICROPHONE
                    else
                        FOREGROUND_SERVICE_TYPE_PHONE_CALL
                )

Try again with https://box.tutpro.com/tmp/baresip.apk.

realPyR3X commented 1 month ago

@juha-h Does not work. Looking at the WG Tunnel code, they seem to be using the lifecycle.launch and wake locks. If the foreground service is still available now,I think you'll need to call the re-register functions when the event occurs from the profile load to reconnect to the sip servers.

realPyR3X commented 1 month ago

With the original apk from f-droid if I leave the app open, switch profiles, and switch back it works. So with the foreground exemptions it might be enough to just call the app init code when you receive the event (to reconnect to the sip servers and get the green bubbles)

juha-h commented 1 month ago

At least with Pixel 7 API 34 emulator baresip with FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED code, I still get

PROCESS ENDED (11507) for package com.tutpro.baresip

when I switch users.

This gets too complicated and hacky to me especially when I don't have a device that supports user switching. The right solution would be a UserSwitchReceiver similar to BootCompletedReceicer that the OS calls when switching users. Unfortunately Android does not support that.

If you have a Linux host and Android Studio available, my suggestion is that you try yourself to modify baresip app's code and try to get user switching to work for you.

realPyR3X commented 1 month ago

@juha-h I will fork and play with it and give you a pull request if I get it working

juha-h commented 1 month ago

@realPyR3X Rather than complicating many apps with weird permissions, better write a single app that cannot be stopped by the OS, has an ACTION_USER_BACKGROUND/FOREGROUND intent watcher and when a switch happens, starts all apps that has been listed in it.

realPyR3X commented 1 month ago

this is a great idea

juha-h commented 1 month ago

I tested and baresip can be started from other apps like this:

            val intent = Intent(Intent.ACTION_MAIN)
            intent.setComponent(
                ComponentName(
                    "com.tutpro.baresip",
                    "com.tutpro.baresip.MainActivity"
                )
            )
            startActivity(intent)

So if someone writes the "restart after user switch" app, beresip would be supported.

juha-h commented 1 month ago

I'll added the above example to Wiki page https://github.com/juha-h/baresip-studio/wiki/Intent-Receiver and will now close this issue.

realPyR3X commented 1 month ago

thank you