I have a custom implementation of VpnService, which needs to perform some additional cleanup on disconnection. Everything works fine when I am stoping VpnService from my application using service bindings, but I need to perform that cleanup when client is disconnecting from the Vpn using system dialog.
So, how can I catch the disconnection and add some handlings to that?
Get VPN Connection status on Android - this could be the solution, but it's not working on android 4+.
From logs point of view there are only two entries:
03-20 03:27:09.478: INFO/Vpn(504): Switched from org.my.package to [Legacy VPN]
03-20 03:27:09.478: DEBUG/Vpn(504): setting state=IDLE, reason=prepare
I just ran into the same issue. VpnService.onRevoke() is not called.
It turns out this happens because I use a custom IBinder defined via AIDL wich I return from onBind(). VpnService implements onBind() too and returns an instance of VpnService.Callback. Which is implemented this way:
private class Callback extends Binder {
@Override
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) {
if (code == IBinder.LAST_CALL_TRANSACTION) {
onRevoke();
return true;
}
return false;
}
}
VpnService.Callback does not use AIDL and just checks if the function code IBinder.LAST_CALL_TRANSACTION was sent. If so it executes onRevoke().
I integrated this code fragment in my custom IBinder implementation and now I receive the onRevoke() message. See the following example:
private final IBinder mBinder = new ServiceBinder();
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public final class ServiceBinder extends ICustomVpnService.Stub
{
... implement methods defined in ICustomVpnService.Stub ....
/**
* Intercept remote method calls and check for "onRevoke" code which
* is represented by IBinder.LAST_CALL_TRANSACTION. If onRevoke message
* was received, call onRevoke() otherwise delegate to super implementation.
*/
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException
{
// see Implementation of android.net.VpnService.Callback.onTransact()
if ( code == IBinder.LAST_CALL_TRANSACTION )
{
onRevoke();
return true;
}
return super.onTransact( code, data, reply, flags );
}
private void onRevoke()
{
// shutdown VpnService, e.g. call VpnService.stopSelf()
}
}
How did I figure it out? I searched the android source code for where onRevoke() is actually invoked. For that I find grepcode (android) pretty helpful. I often read the android source to understand how things work.