From 49b1539722063a53573fb859f543967ebff5ce14 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 24 Feb 2021 23:23:47 +0100 Subject: implement service binding in order to fix remote service exception during foreground service start --- app/src/main/java/de/blinkt/openvpn/LaunchVPN.java | 3 +- .../de/blinkt/openvpn/core/OpenVPNService.java | 25 +++----- .../de/blinkt/openvpn/core/VPNLaunchHelper.java | 17 ------ .../se/leap/bitmaskclient/base/MainActivity.java | 40 +++++++----- .../bitmaskclient/base/fragments/EipFragment.java | 6 +- .../leap/bitmaskclient/base/models/Constants.java | 2 +- .../main/java/se/leap/bitmaskclient/eip/EIP.java | 52 +++++++++++++--- .../java/se/leap/bitmaskclient/eip/EipCommand.java | 20 +++--- .../leap/bitmaskclient/eip/EipSetupObserver.java | 8 +++ .../se/leap/bitmaskclient/eip/VoidVpnService.java | 6 ++ .../bitmaskclient/eip/VpnNotificationManager.java | 71 ++++++++++++++-------- 11 files changed, 152 insertions(+), 98 deletions(-) (limited to 'app/src/main/java') diff --git a/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java b/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java index b148d04d..3f45f391 100644 --- a/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java +++ b/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java @@ -25,6 +25,7 @@ import de.blinkt.openvpn.core.VPNLaunchHelper; import de.blinkt.openvpn.core.VpnStatus; import se.leap.bitmaskclient.base.MainActivity; import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.eip.EipCommand; import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_PREPARE_VPN; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PROFILE; @@ -119,7 +120,7 @@ public class LaunchVPN extends Activity { if(!mhideLog && showLogWindow) showLogWindow(); - VPNLaunchHelper.startOpenVpn(mSelectedProfile, getBaseContext()); + EipCommand.launchVPNProfile(getApplicationContext(), mSelectedProfile); finish(); } else if (resultCode == Activity.RESULT_CANCELED) { diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java index 1670c0be..6be8db25 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -46,6 +46,7 @@ import de.blinkt.openvpn.core.VpnStatus.StateListener; import de.blinkt.openvpn.core.connection.Connection; import de.blinkt.openvpn.core.connection.Obfs4Connection; import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.eip.EipStatus; import se.leap.bitmaskclient.eip.VpnNotificationManager; import se.leap.bitmaskclient.firewall.FirewallManager; import se.leap.bitmaskclient.pluggableTransports.Shapeshifter; @@ -92,11 +93,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac private Shapeshifter shapeshifter; private FirewallManager firewallManager; - private static final int PRIORITY_MIN = -2; - private static final int PRIORITY_DEFAULT = 0; - private static final int PRIORITY_MAX = 2; - - private final IBinder mBinder = new IOpenVPNServiceInternal.Stub() { @Override @@ -118,6 +114,11 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac public boolean isVpnRunning() throws RemoteException { return OpenVPNService.this.isVpnRunning(); } + + @Override + public void startWithForegroundNotification() throws RemoteException { + OpenVPNService.this.startWithForegroundNotification(); + } }; // From: http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java @@ -280,18 +281,11 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac } + @Override public void startWithForegroundNotification() { // Always show notification here to avoid problem with startForeground timeout notificationManager.createOpenVpnNotificationChannel(); - notificationManager.buildOpenVpnNotification( - mProfile != null ? mProfile.mName : "", - mProfile != null && mProfile.mUsePluggableTransports, - VpnStatus.getLastCleanLogMessage(this), - VpnStatus.getLastCleanLogMessage(this), - ConnectionStatus.LEVEL_START, - 0, - NOTIFICATION_CHANNEL_NEWSTATUS_ID, - this::onNotificationBuild); + notificationManager.buildForegroundServiceNotification(EipStatus.getInstance().getLevel(), this::onNotificationBuild); } @Override @@ -539,7 +533,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac public void onCreate() { super.onCreate(); notificationManager = new VpnNotificationManager(this); - startWithForegroundNotification(); firewallManager = new FirewallManager(this, true); } @@ -558,7 +551,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac VpnStatus.removeStateListener(this); VpnStatus.flushLog(); firewallManager.onDestroy(); - notificationManager.cancelAllNotifications(); + notificationManager.deleteOpenvpnNotificationChannel(); } private String getTunConfigString() { diff --git a/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java b/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java index 7c742746..540ca043 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java +++ b/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java @@ -7,7 +7,6 @@ package de.blinkt.openvpn.core; import android.annotation.TargetApi; import android.content.Context; -import android.content.Intent; import android.os.Build; import java.io.File; @@ -18,7 +17,6 @@ import java.util.Arrays; import java.util.Vector; import se.leap.bitmaskclient.R; -import de.blinkt.openvpn.VpnProfile; public class VPNLaunchHelper { private static final String MININONPIEVPN = "nopie_openvpn"; @@ -120,7 +118,6 @@ public class VPNLaunchHelper { return false; } - return true; } catch (IOException e) { VpnStatus.logException(e); @@ -129,20 +126,6 @@ public class VPNLaunchHelper { } - - public static void startOpenVpn(VpnProfile startprofile, Context context) { - Intent startVPN = startprofile.prepareStartService(context); - if (startVPN != null) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) - //noinspection NewApi - context.startForegroundService(startVPN); - else - context.startService(startVPN); - - } - } - - public static String getConfigFilePath(Context context) { return context.getCacheDir().getAbsolutePath() + "/" + OVPNCONFIGFILE; } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java b/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java index 676e6c82..a7a14ed0 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java @@ -20,13 +20,14 @@ package se.leap.bitmaskclient.base; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; +import android.util.Log; + import androidx.annotation.StringRes; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentTransaction; -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.AppCompatActivity; -import android.util.Log; import org.json.JSONException; import org.json.JSONObject; @@ -35,24 +36,27 @@ import java.util.Observable; import java.util.Observer; import se.leap.bitmaskclient.R; -import se.leap.bitmaskclient.base.fragments.NavigationDrawerFragment; -import se.leap.bitmaskclient.eip.EIP; -import se.leap.bitmaskclient.eip.EipCommand; -import se.leap.bitmaskclient.eip.EipSetupListener; -import se.leap.bitmaskclient.eip.EipSetupObserver; import se.leap.bitmaskclient.base.fragments.EipFragment; import se.leap.bitmaskclient.base.fragments.ExcludeAppsFragment; import se.leap.bitmaskclient.base.fragments.LogFragment; +import se.leap.bitmaskclient.base.fragments.MainActivityErrorDialog; +import se.leap.bitmaskclient.base.fragments.NavigationDrawerFragment; import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.base.models.ProviderObservable; -import se.leap.bitmaskclient.providersetup.models.LeapSRPSession; -import se.leap.bitmaskclient.providersetup.activities.LoginActivity; import se.leap.bitmaskclient.base.utils.PreferenceHelper; -import se.leap.bitmaskclient.base.fragments.MainActivityErrorDialog; +import se.leap.bitmaskclient.eip.EIP; +import se.leap.bitmaskclient.eip.EipCommand; +import se.leap.bitmaskclient.eip.EipSetupListener; +import se.leap.bitmaskclient.eip.EipSetupObserver; +import se.leap.bitmaskclient.providersetup.activities.LoginActivity; +import se.leap.bitmaskclient.providersetup.models.LeapSRPSession; +import static se.leap.bitmaskclient.R.string.downloading_vpn_certificate_failed; +import static se.leap.bitmaskclient.R.string.vpn_certificate_user_message; import static se.leap.bitmaskclient.base.models.Constants.ASK_TO_CANCEL_VPN; import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_CODE; import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_KEY; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_LAUNCH_VPN; import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_PREPARE_VPN; import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START; import static se.leap.bitmaskclient.base.models.Constants.EIP_REQUEST; @@ -61,16 +65,14 @@ import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_CONFIGURE import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_LOG_IN; import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_SWITCH_PROVIDER; import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.storeProviderInPreferences; +import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_INVALID_VPN_CERTIFICATE; +import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_VPN_PREPARE; import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORID; import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS; import static se.leap.bitmaskclient.providersetup.ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE; import static se.leap.bitmaskclient.providersetup.ProviderAPI.INCORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE; import static se.leap.bitmaskclient.providersetup.ProviderAPI.USER_MESSAGE; -import static se.leap.bitmaskclient.R.string.downloading_vpn_certificate_failed; -import static se.leap.bitmaskclient.R.string.vpn_certificate_user_message; -import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_INVALID_VPN_CERTIFICATE; -import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_VPN_PREPARE; -import static se.leap.bitmaskclient.base.utils.PreferenceHelper.storeProviderInPreferences; public class MainActivity extends AppCompatActivity implements EipSetupListener, Observer, ExcludeAppsFragment.ExcludedAppsCallback { @@ -259,6 +261,12 @@ public class MainActivity extends AppCompatActivity implements EipSetupListener, showMainActivityErrorDialog(getString(R.string.vpn_error_establish), ERROR_VPN_PREPARE); } break; + case EIP_ACTION_LAUNCH_VPN: + if (resultCode == RESULT_CANCELED) { + String error = resultData.getString(ERRORS); + showMainActivityErrorDialog(error); + } + break; } } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java index 4ff80ea6..5d88d864 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java @@ -52,6 +52,7 @@ import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; import butterknife.Unbinder; +import de.blinkt.openvpn.core.ConnectionStatus; import de.blinkt.openvpn.core.IOpenVPNServiceInternal; import de.blinkt.openvpn.core.OpenVPNService; import de.blinkt.openvpn.core.VpnStatus; @@ -319,10 +320,11 @@ public class EipFragment extends Fragment implements Observer { } else { EipCommand.startVPN(context.getApplicationContext(), false); } - vpnStateImage.showProgress(); + EipStatus.getInstance().updateState("RECONNECTING", "", 0, ConnectionStatus.LEVEL_START); + /* vpnStateImage.showProgress(); routedText.setVisibility(GONE); vpnRoute.setVisibility(GONE); - colorBackgroundALittle(); + colorBackgroundALittle();*/ } protected void stopEipIfPossible() { diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java index e60019fc..8adf7744 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java @@ -80,7 +80,7 @@ public interface Constants { String EIP_ACTION_START_BLOCKING_VPN = "se.leap.bitmaskclient.EIP_ACTION_START_BLOCKING_VPN"; String EIP_ACTION_STOP_BLOCKING_VPN = "se.leap.bitmaskclient.EIP_ACTION_STOP_BLOCKING_VPN"; String EIP_ACTION_PREPARE_VPN = "se.leap.bitmaskclient.EIP_ACTION_PREPARE_VPN"; - String EIP_ACTION_CONFIGURE_TETHERING = "se.leap.bitmaskclient.EIP_ACTION_CONFIGURE_TETHERING"; + String EIP_ACTION_LAUNCH_VPN = "se.leap.bitmaskclient.EIP_ACTION_LAUNCH_VPN"; String EIP_RECEIVER = "EIP.RECEIVER"; String EIP_REQUEST = "EIP.REQUEST"; diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java index 66b7c6cf..ae6bdf39 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -22,16 +22,18 @@ import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; +import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.os.ResultReceiver; +import android.util.Log; + import androidx.annotation.NonNull; import androidx.annotation.StringRes; import androidx.annotation.WorkerThread; import androidx.core.app.JobIntentService; import androidx.localbroadcastmanager.content.LocalBroadcastManager; -import android.util.Log; import org.json.JSONException; import org.json.JSONObject; @@ -49,20 +51,23 @@ import de.blinkt.openvpn.core.IOpenVPNServiceInternal; import de.blinkt.openvpn.core.OpenVPNService; import de.blinkt.openvpn.core.VpnStatus; import de.blinkt.openvpn.core.connection.Connection; +import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.OnBootReceiver; import se.leap.bitmaskclient.base.models.ProviderObservable; -import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.utils.PreferenceHelper; import static android.app.Activity.RESULT_CANCELED; import static android.app.Activity.RESULT_OK; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; +import static se.leap.bitmaskclient.R.string.vpn_certificate_is_invalid; +import static se.leap.bitmaskclient.R.string.warning_client_parsing_error_gateways; import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_GATEWAY_SETUP_OBSERVER_EVENT; import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_KEY; import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_CHECK_CERT_VALIDITY; -import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_CONFIGURE_TETHERING; import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_IS_RUNNING; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_LAUNCH_VPN; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_PREPARE_VPN; import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START; import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START_ALWAYS_ON_VPN; import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START_BLOCKING_VPN; @@ -75,13 +80,11 @@ import static se.leap.bitmaskclient.base.models.Constants.EIP_RESTART_ON_BOOT; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PROFILE; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; -import static se.leap.bitmaskclient.R.string.vpn_certificate_is_invalid; -import static se.leap.bitmaskclient.R.string.warning_client_parsing_error_gateways; +import static se.leap.bitmaskclient.base.utils.ConfigHelper.ensureNotOnMainThread; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUsePluggableTransports; import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_INVALID_VPN_CERTIFICATE; import static se.leap.bitmaskclient.eip.EIP.EIPErrors.NO_MORE_GATEWAYS; import static se.leap.bitmaskclient.eip.EipResultBroadcast.tellToReceiverOrBroadcast; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.ensureNotOnMainThread; -import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUsePluggableTransports; /** * EIP is the abstract base class for interacting with and managing the Encrypted @@ -116,7 +119,8 @@ public final class EIP extends JobIntentService implements Observer { UNKNOWN, ERROR_INVALID_VPN_CERTIFICATE, NO_MORE_GATEWAYS, - ERROR_VPN_PREPARE + ERROR_VPN_PREPARE, + ERROR_INVALID_PROFILE } /** @@ -195,8 +199,9 @@ public final class EIP extends JobIntentService implements Observer { disconnect(); earlyRoutes(); break; - case EIP_ACTION_CONFIGURE_TETHERING: - Log.d(TAG, "TODO: implement tethering configuration"); + case EIP_ACTION_LAUNCH_VPN: + VpnProfile profile = (VpnProfile) intent.getSerializableExtra(PROVIDER_PROFILE); + launchVpn(profile); break; } } @@ -409,6 +414,33 @@ public final class EIP extends JobIntentService implements Observer { return false; } + /** + * creates an OpenVpnServiceConnection if necessary and starts OpenVPN as foreground service + */ + private void launchVpn(VpnProfile vpnProfile) { + Bundle result = new Bundle(); + + Intent startVPN = vpnProfile.prepareStartService(getApplicationContext()); + if (startVPN != null) { + try { + initOpenVpnServiceConnection(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + //noinspection NewApi + getApplicationContext().startForegroundService(startVPN); + openVpnServiceConnection.getService().startWithForegroundNotification(); + } else { + getApplicationContext().startService(startVPN); + } + } catch (InterruptedException | IllegalStateException | RemoteException e) { + setErrorResult(result, R.string.vpn_error_establish, null); + tellToReceiverOrBroadcast(this.getApplicationContext(), EIP_ACTION_PREPARE_VPN, RESULT_CANCELED); + } + } else { + setErrorResult(result, R.string.vpn_error_establish, null); + tellToReceiverOrBroadcast(this.getApplicationContext(), EIP_ACTION_PREPARE_VPN, RESULT_CANCELED); + } + } + private @StringRes int getStringResourceForNoMoreGateways() { if (ProviderObservable.getInstance().getCurrentProvider().supportsPluggableTransports()) { diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipCommand.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipCommand.java index 0650e8cd..7f330f0d 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EipCommand.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipCommand.java @@ -9,14 +9,17 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; +import de.blinkt.openvpn.VpnProfile; + import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_CHECK_CERT_VALIDITY; -import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_CONFIGURE_TETHERING; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_LAUNCH_VPN; import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START; import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START_BLOCKING_VPN; import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_STOP; import static se.leap.bitmaskclient.base.models.Constants.EIP_EARLY_ROUTES; import static se.leap.bitmaskclient.base.models.Constants.EIP_N_CLOSEST_GATEWAY; import static se.leap.bitmaskclient.base.models.Constants.EIP_RECEIVER; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PROFILE; /** * Use this class to send commands to EIP @@ -73,6 +76,12 @@ public class EipCommand { execute(context, EIP_ACTION_STOP); } + public static void launchVPNProfile(@NonNull Context context, VpnProfile vpnProfile) { + Intent baseIntent = new Intent(); + baseIntent.putExtra(PROVIDER_PROFILE, vpnProfile); + execute(context, EIP_ACTION_LAUNCH_VPN, null, baseIntent); + } + @VisibleForTesting public static void stopVPN(@NonNull Context context, ResultReceiver resultReceiver) { execute(context, EIP_ACTION_STOP, resultReceiver, null); @@ -87,13 +96,4 @@ public class EipCommand { execute(context, EIP_ACTION_CHECK_CERT_VALIDITY, resultReceiver, null); } - public static void configureTethering(@NonNull Context context) { - execute(context, EIP_ACTION_CONFIGURE_TETHERING); - } - - @VisibleForTesting - public static void configureTethering(@NonNull Context context, ResultReceiver resultReceiver) { - execute(context, EIP_ACTION_CONFIGURE_TETHERING); - } - } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java index f35e5e30..a8e71f64 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java @@ -54,6 +54,7 @@ import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_GATEWAY_SETU import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_PROVIDER_API_EVENT; import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_CODE; import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_KEY; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_LAUNCH_VPN; import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_PREPARE_VPN; import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START; import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START_ALWAYS_ON_VPN; @@ -230,6 +231,13 @@ public class EipSetupObserver extends BroadcastReceiver implements VpnStatus.Sta EipStatus.refresh(); } break; + case EIP_ACTION_LAUNCH_VPN: + if (resultCode == RESULT_CANCELED) { + VpnStatus.logError("Error starting VpnService."); + finishGatewaySetup(false); + EipStatus.refresh(); + } + break; default: break; } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java index 0c46f8cd..476dda77 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java @@ -99,6 +99,12 @@ public class VoidVpnService extends VpnService implements Observer, VpnNotificat closeFd(); } + @Override + public void onDestroy() { + super.onDestroy(); + notificationManager.deleteVoidVpnNotificationChannel(); + } + private void stop() { if (thread != null) { thread.interrupt(); diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnNotificationManager.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnNotificationManager.java index 6fd33352..b007715b 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnNotificationManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnNotificationManager.java @@ -31,7 +31,6 @@ import android.text.Spannable; import android.text.SpannableString; import android.text.TextUtils; import android.text.style.StyleSpan; -import android.util.Log; import android.widget.RemoteViews; import androidx.annotation.NonNull; @@ -50,11 +49,11 @@ import static android.os.Build.VERSION_CODES.O; import static android.text.TextUtils.isEmpty; import static androidx.core.app.NotificationCompat.PRIORITY_DEFAULT; import static androidx.core.app.NotificationCompat.PRIORITY_MAX; -import static androidx.core.app.NotificationCompat.PRIORITY_MIN; import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_NONETWORK; import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT; import static se.leap.bitmaskclient.base.MainActivity.ACTION_SHOW_VPN_FRAGMENT; import static se.leap.bitmaskclient.base.models.Constants.ASK_TO_CANCEL_VPN; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START; import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_STOP_BLOCKING_VPN; /** @@ -96,6 +95,37 @@ public class VpnNotificationManager { ); } + + public void buildForegroundServiceNotification(ConnectionStatus connectionStatus, + VpnServiceCallback callback) { + String message = ""; + // if the app was killed by the system getLastCleanLogMessage returns an empty string + // because the state doesn't get persisted. We can use LEVEL_NOTCONNECTED as an indicator for + // that case because the openvpn service won't be connected then + if (connectionStatus == ConnectionStatus.LEVEL_NOTCONNECTED) { + message = context.getString(R.string.eip_state_not_connected); + } else { + message = VpnStatus.getLastCleanLogMessage(context); + } + + NotificationCompat.Action.Builder actionBuilder = new NotificationCompat.Action.Builder(0, + context.getString(R.string.vpn_button_turn_on), getStartOpenvpnIntent()); + + buildVpnNotification( + "", + message, + null, + "", + connectionStatus, + OpenVPNService.NOTIFICATION_CHANNEL_NEWSTATUS_ID, + PRIORITY_DEFAULT, + 0, + getMainActivityIntent(), + actionBuilder.build(), + callback + ); + } + public void buildOpenVpnNotification(String profileName, boolean isObfuscated, String msg, String tickerText, ConnectionStatus status, long when, String notificationChannelNewstatusId, VpnServiceCallback vpnServiceCallback) { @@ -147,15 +177,6 @@ public class VpnNotificationManager { contentIntent = getUserInputIntent(msg); else contentIntent = getMainActivityIntent(); - - int priority; - if (OpenVPNService.NOTIFICATION_CHANNEL_NEWSTATUS_ID.equals(notificationChannelNewstatusId)) { - priority = PRIORITY_DEFAULT; - } else { - // background channel - priority = PRIORITY_MIN; - } - buildVpnNotification( title, msg, @@ -163,7 +184,7 @@ public class VpnNotificationManager { tickerText, status, notificationChannelNewstatusId, - priority, + PRIORITY_DEFAULT, when, contentIntent, actionBuilder.build(), @@ -174,11 +195,17 @@ public class VpnNotificationManager { buildOpenVpnNotification(profileName, isObfuscated, msg, tickerText, status, when, notificationChannelNewstatusId, null); } + public void deleteOpenvpnNotificationChannel() { + compatNotificationManager.cancelAll(); + compatNotificationManager.deleteNotificationChannel(OpenVPNService.NOTIFICATION_CHANNEL_NEWSTATUS_ID); + } - public void cancelAllNotifications() { + public void deleteVoidVpnNotificationChannel() { compatNotificationManager.cancelAll(); + compatNotificationManager.deleteNotificationChannel(VoidVpnService.NOTIFICATION_CHANNEL_NEWSTATUS_ID); } + @TargetApi(O) public void createVoidVpnNotificationChannel() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { @@ -236,18 +263,6 @@ public class VpnNotificationManager { return remoteViews; } - public void buildOpenVpnForegroundNotification(VpnServiceCallback vpnServiceCallback) { - buildOpenVpnNotification("", - false, - VpnStatus.getLastCleanLogMessage(context.getApplicationContext()), - VpnStatus.getLastCleanLogMessage(context.getApplicationContext()), - ConnectionStatus.LEVEL_START, - 0, - OpenVPNService.NOTIFICATION_CHANNEL_NEWSTATUS_ID, - vpnServiceCallback - ); - } - private void buildVpnNotification(String title, String message, CharSequence bigMessage, String tickerText, ConnectionStatus status, String notificationChannelNewstatusId, int priority, long when, PendingIntent contentIntent, NotificationCompat.Action notificationAction, VpnServiceCallback vpnServiceCallback) { @@ -299,6 +314,12 @@ public class VpnNotificationManager { return PendingIntent.getActivity(context, 0, startActivity, PendingIntent.FLAG_CANCEL_CURRENT); } + private PendingIntent getStartOpenvpnIntent() { + Intent startIntent = new Intent(context, EIP.class); + startIntent.setAction(EIP_ACTION_START); + return PendingIntent.getService(context, 0, startIntent, PendingIntent.FLAG_CANCEL_CURRENT); + } + private PendingIntent getStopVoidVpnIntent() { Intent stopVoidVpnIntent = new Intent (context, VoidVpnService.class); stopVoidVpnIntent.setAction(EIP_ACTION_STOP_BLOCKING_VPN); -- cgit v1.2.3