diff --git a/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java b/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java index fb40a613..e5f2bc70 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java +++ b/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java @@ -43,6 +43,7 @@ import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.ParcelFileDescriptor; +import android.provider.Settings; import android.util.Pair; import android.util.SparseArray; import android.widget.Toast; @@ -214,6 +215,26 @@ public class CaptureService extends VpnService implements Runnable { return START_NOT_STICKY; } + private static boolean alwaysOnVpnErrorLogged = false; + + // Android does not provide a reliable API to track the always-on VPN state + // This function tries to detect but may fail to do so + private boolean isAlwaysOnVpnDetected() { + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) + return isAlwaysOn(); + + try { + String always_on_vpn_app = Settings.Secure.getString(getContentResolver(), "always_on_vpn_app"); + return always_on_vpn_app.equals(getPackageName()); + } catch (Exception e) { + if (!alwaysOnVpnErrorLogged) { + Log.w(TAG, "Querying the always-on VPN state failed: " + e); + alwaysOnVpnErrorLogged = true; + } + return false; + } + } + @Override public int onStartCommand(@Nullable Intent intent, int flags, int startId) { mStopping = false; @@ -262,8 +283,7 @@ public class CaptureService extends VpnService implements Runnable { mIsAlwaysOnVPN = false; } - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) - mIsAlwaysOnVPN |= isAlwaysOn(); + mIsAlwaysOnVPN |= isAlwaysOnVpnDetected(); Log.d(TAG, "alwaysOn? " + mIsAlwaysOnVPN); if(mIsAlwaysOnVPN) { @@ -938,6 +958,20 @@ public class CaptureService extends VpnService implements Runnable { return((INSTANCE != null) && INSTANCE.mIsAlwaysOnVPN); } + public static boolean checkAlwaysOnVpnActivated() { + CaptureService instance = INSTANCE; + if (instance == null) + return false; + + if (!instance.mIsAlwaysOnVPN && instance.isAlwaysOnVpnDetected()) { + Log.i(TAG, "Always-on VPN was activated"); + instance.mIsAlwaysOnVPN = true; + return true; + } + + return false; + } + @RequiresApi(api = Build.VERSION_CODES.Q) public static boolean isLockdownVPN() { return ((INSTANCE != null) && INSTANCE.isLockdownEnabled()); @@ -1090,6 +1124,8 @@ public class CaptureService extends VpnService implements Runnable { return (ifname != null) ? ifname : ""; } + + // Inside the mCaptureThread @Override public void run() { diff --git a/app/src/main/java/com/emanuelef/remote_capture/fragments/StatusFragment.java b/app/src/main/java/com/emanuelef/remote_capture/fragments/StatusFragment.java index 6360d272..0d47f86b 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/fragments/StatusFragment.java +++ b/app/src/main/java/com/emanuelef/remote_capture/fragments/StatusFragment.java @@ -100,6 +100,8 @@ public class StatusFragment extends Fragment implements AppStateListener, MenuPr @Override public void onResume() { super.onResume(); + + CaptureService.checkAlwaysOnVpnActivated(); refreshStatus(); }