diff options
author | cyBerta <cyberta@riseup.net> | 2020-12-29 00:54:08 +0100 |
---|---|---|
committer | cyBerta <cyberta@riseup.net> | 2020-12-29 00:54:08 +0100 |
commit | 6b032b751324a30120cfaabe88940f95171df11f (patch) | |
tree | b6b26b84358726a02e27558562e7e9ea70a7aaa0 /app/src/main/java/se/leap/bitmaskclient/eip | |
parent | 16da1eeb5180cbb4a0d916785a08ccbcd3c1d74e (diff) |
new year cleanup: restructure messy project
Diffstat (limited to 'app/src/main/java/se/leap/bitmaskclient/eip')
13 files changed, 812 insertions, 72 deletions
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 e0c96ebb..e5cf70be 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -49,39 +49,39 @@ 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.OnBootReceiver; -import se.leap.bitmaskclient.ProviderObservable; +import se.leap.bitmaskclient.base.OnBootReceiver; +import se.leap.bitmaskclient.base.models.ProviderObservable; import se.leap.bitmaskclient.R; -import se.leap.bitmaskclient.utils.PreferenceHelper; +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.Constants.BROADCAST_GATEWAY_SETUP_OBSERVER_EVENT; -import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY; -import static se.leap.bitmaskclient.Constants.EIP_ACTION_CHECK_CERT_VALIDITY; -import static se.leap.bitmaskclient.Constants.EIP_ACTION_CONFIGURE_TETHERING; -import static se.leap.bitmaskclient.Constants.EIP_ACTION_IS_RUNNING; -import static se.leap.bitmaskclient.Constants.EIP_ACTION_START; -import static se.leap.bitmaskclient.Constants.EIP_ACTION_START_ALWAYS_ON_VPN; -import static se.leap.bitmaskclient.Constants.EIP_ACTION_START_BLOCKING_VPN; -import static se.leap.bitmaskclient.Constants.EIP_ACTION_STOP; -import static se.leap.bitmaskclient.Constants.EIP_ACTION_STOP_BLOCKING_VPN; -import static se.leap.bitmaskclient.Constants.EIP_EARLY_ROUTES; -import static se.leap.bitmaskclient.Constants.EIP_N_CLOSEST_GATEWAY; -import static se.leap.bitmaskclient.Constants.EIP_RECEIVER; -import static se.leap.bitmaskclient.Constants.EIP_RESTART_ON_BOOT; -import static se.leap.bitmaskclient.Constants.PROVIDER_PROFILE; -import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE; -import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES; +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_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; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_STOP; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_STOP_BLOCKING_VPN; +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.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.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.utils.ConfigHelper.ensureNotOnMainThread; -import static se.leap.bitmaskclient.utils.PreferenceHelper.getUsePluggableTransports; +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 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 25450f56..39d4e33e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EipCommand.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipCommand.java @@ -11,14 +11,14 @@ import androidx.annotation.VisibleForTesting; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import static se.leap.bitmaskclient.Constants.EIP_ACTION_CHECK_CERT_VALIDITY; -import static se.leap.bitmaskclient.Constants.EIP_ACTION_CONFIGURE_TETHERING; -import static se.leap.bitmaskclient.Constants.EIP_ACTION_START; -import static se.leap.bitmaskclient.Constants.EIP_ACTION_START_BLOCKING_VPN; -import static se.leap.bitmaskclient.Constants.EIP_ACTION_STOP; -import static se.leap.bitmaskclient.Constants.EIP_EARLY_ROUTES; -import static se.leap.bitmaskclient.Constants.EIP_N_CLOSEST_GATEWAY; -import static se.leap.bitmaskclient.Constants.EIP_RECEIVER; +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_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; /** * Use this class to send commands to EIP diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipResultBroadcast.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipResultBroadcast.java index 92d1338c..68d9c8ad 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EipResultBroadcast.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipResultBroadcast.java @@ -8,10 +8,10 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager; import android.util.Log; import static android.content.Intent.CATEGORY_DEFAULT; -import static se.leap.bitmaskclient.Constants.BROADCAST_EIP_EVENT; -import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_CODE; -import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY; -import static se.leap.bitmaskclient.Constants.EIP_REQUEST; +import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_EIP_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_REQUEST; public class EipResultBroadcast { private static final String TAG = EipResultBroadcast.class.getSimpleName(); diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupListener.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupListener.java new file mode 100644 index 00000000..13d9bdec --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupListener.java @@ -0,0 +1,12 @@ +package se.leap.bitmaskclient.eip; + +import android.content.Intent; + +/** + * Created by cyberta on 05.12.18. + */ +public interface EipSetupListener { + void handleEipEvent(Intent intent); + + void handleProviderApiEvent(Intent intent); +} diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java new file mode 100644 index 00000000..1c101e2d --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java @@ -0,0 +1,374 @@ +/** + * Copyright (c) 2020 LEAP Encryption Access Project and contributers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package se.leap.bitmaskclient.eip; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.util.Log; + +import androidx.localbroadcastmanager.content.LocalBroadcastManager; + +import org.json.JSONObject; + +import java.util.Vector; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +import de.blinkt.openvpn.LaunchVPN; +import de.blinkt.openvpn.VpnProfile; +import de.blinkt.openvpn.core.ConnectionStatus; +import de.blinkt.openvpn.core.LogItem; +import de.blinkt.openvpn.core.VpnStatus; +import se.leap.bitmaskclient.base.models.Provider; +import se.leap.bitmaskclient.providersetup.ProviderAPI; +import se.leap.bitmaskclient.providersetup.ProviderAPICommand; +import se.leap.bitmaskclient.base.models.ProviderObservable; +import se.leap.bitmaskclient.appUpdate.DownloadServiceCommand; +import se.leap.bitmaskclient.base.utils.PreferenceHelper; + +import static android.app.Activity.RESULT_CANCELED; +import static android.content.Intent.CATEGORY_DEFAULT; +import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET; +import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_NOTCONNECTED; +import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_EIP_EVENT; +import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_GATEWAY_SETUP_OBSERVER_EVENT; +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_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_EARLY_ROUTES; +import static se.leap.bitmaskclient.base.models.Constants.EIP_REQUEST; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PROFILE; +import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE; +import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_DOWNLOADED_GEOIP_JSON; +import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE; +import static se.leap.bitmaskclient.providersetup.ProviderAPI.INCORRECTLY_DOWNLOADED_GEOIP_JSON; +import static se.leap.bitmaskclient.appUpdate.DownloadServiceCommand.CHECK_VERSION_FILE; + +/** + * Created by cyberta on 05.12.18. + */ +public class EipSetupObserver extends BroadcastReceiver implements VpnStatus.StateListener, VpnStatus.LogListener { + + private static final String TAG = EipSetupObserver.class.getName(); + + //The real timout is 4*2s + 1*4s + 1*8s + 1*16s + 1*32s + 1*64s = 132 s; + private static final String TIMEOUT = "4"; + private static final int UPDATE_CHECK_TIMEOUT = 1000*60*60*24*7; + private Context context; + private VpnProfile setupVpnProfile; + private String observedProfileFromVpnStatus; + AtomicBoolean changingGateway = new AtomicBoolean(false); + AtomicInteger setupNClosestGateway = new AtomicInteger(); + AtomicInteger reconnectTry = new AtomicInteger(); + private Vector<EipSetupListener> listeners = new Vector<>(); + private SharedPreferences preferences; + private static EipSetupObserver instance; + + private EipSetupObserver(Context context, SharedPreferences preferences) { + this.context = context; + this.preferences = preferences; + IntentFilter updateIntentFilter = new IntentFilter(BROADCAST_GATEWAY_SETUP_OBSERVER_EVENT); + updateIntentFilter.addAction(BROADCAST_EIP_EVENT); + updateIntentFilter.addAction(BROADCAST_PROVIDER_API_EVENT); + updateIntentFilter.addCategory(CATEGORY_DEFAULT); + LocalBroadcastManager.getInstance(context.getApplicationContext()).registerReceiver(this, updateIntentFilter); + instance = this; + VpnStatus.addLogListener(this); + } + + public static void init(Context context, SharedPreferences preferences) { + if (instance == null) { + instance = new EipSetupObserver(context, preferences); + } + } + + public static boolean reconnectingWithDifferentGateway() { + return instance.setupNClosestGateway.get() > 0; + } + + public static int connectionRetry() { + return instance.reconnectTry.get(); + } + + public static int gatewayOrder() { + return instance.setupNClosestGateway.get(); + } + + public static synchronized void addListener(EipSetupListener listener) { + if (instance.listeners.contains(listener)) { + return; + } + instance.listeners.add(listener); + } + + public static synchronized void removeListener(EipSetupListener listener) { + instance.listeners.remove(listener); + } + + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action == null) { + return; + } + + switch (action) { + case BROADCAST_GATEWAY_SETUP_OBSERVER_EVENT: + handleGatewaySetupObserverEvent(intent); + break; + case BROADCAST_EIP_EVENT: + handleEipEvent(intent); + break; + case BROADCAST_PROVIDER_API_EVENT: + handleProviderApiEvent(intent); + break; + default: + break; + } + } + + private void handleProviderApiEvent(Intent intent) { + int resultCode = intent.getIntExtra(BROADCAST_RESULT_CODE, RESULT_CANCELED); + Bundle resultData = intent.getParcelableExtra(BROADCAST_RESULT_KEY); + if (resultData == null) { + resultData = Bundle.EMPTY; + } + + Provider provider; + switch (resultCode) { + case CORRECTLY_DOWNLOADED_EIP_SERVICE: + Log.d(TAG, "correctly updated service json"); + provider = resultData.getParcelable(PROVIDER_KEY); + ProviderObservable.getInstance().updateProvider(provider); + PreferenceHelper.storeProviderInPreferences(preferences, provider); + if (EipStatus.getInstance().isDisconnected()) { + EipCommand.startVPN(context.getApplicationContext(), true); + } + break; + case CORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE: + provider = resultData.getParcelable(PROVIDER_KEY); + ProviderObservable.getInstance().updateProvider(provider); + PreferenceHelper.storeProviderInPreferences(preferences, provider); + EipCommand.startVPN(context.getApplicationContext(), true); + break; + case CORRECTLY_DOWNLOADED_GEOIP_JSON: + provider = resultData.getParcelable(PROVIDER_KEY); + ProviderObservable.getInstance().updateProvider(provider); + PreferenceHelper.storeProviderInPreferences(preferences, provider); + maybeStartEipService(resultData); + break; + case INCORRECTLY_DOWNLOADED_GEOIP_JSON: + maybeStartEipService(resultData); + break; + default: + break; + } + + for (EipSetupListener listener : listeners) { + listener.handleProviderApiEvent(intent); + } + } + + private void maybeStartEipService(Bundle resultData) { + if (resultData.getBoolean(EIP_ACTION_START)) { + boolean earlyRoutes = resultData.getBoolean(EIP_EARLY_ROUTES); + EipCommand.startVPN(context.getApplicationContext(), earlyRoutes); + } + } + + + private void handleEipEvent(Intent intent) { + int resultCode = intent.getIntExtra(BROADCAST_RESULT_CODE, RESULT_CANCELED); + Bundle result = intent.getBundleExtra(BROADCAST_RESULT_KEY); + String eipRequest = result.getString(EIP_REQUEST); + EIP.EIPErrors error = EIP.EIPErrors.UNKNOWN; + try { + JSONObject jsonObject = new JSONObject(result.getString(EIP.ERRORS)); + error = EIP.EIPErrors.valueOf(jsonObject.getString(EIP.ERRORID)); + } catch (Exception e) { + //ignore + } + if (eipRequest == null) { + return; + } + switch (eipRequest) { + case EIP_ACTION_START: + case EIP_ACTION_START_ALWAYS_ON_VPN: + if (resultCode == RESULT_CANCELED) { + //setup failed + if (error == EIP.EIPErrors.NO_MORE_GATEWAYS) { + finishGatewaySetup(false); + EipCommand.startBlockingVPN(context.getApplicationContext()); + } else { + //FIXME: + finishGatewaySetup(false); + EipCommand.stopVPN(context); + EipStatus.refresh(); + } + } + break; + case EIP_ACTION_PREPARE_VPN: + if (resultCode == RESULT_CANCELED) { + VpnStatus.logError("Error preparing VpnService."); + finishGatewaySetup(false); + EipStatus.refresh(); + } + break; + default: + break; + } + + for (EipSetupListener listener : listeners) { + listener.handleEipEvent(intent); + } + } + + private void handleGatewaySetupObserverEvent(Intent event) { + if (observedProfileFromVpnStatus != null || setupVpnProfile != null) { + //finish last setup observation + Log.d(TAG, "finish last gateway setup"); + finishGatewaySetup(true); + } + + VpnProfile vpnProfile = (VpnProfile) event.getSerializableExtra(PROVIDER_PROFILE); + if (vpnProfile == null) { + Log.e(TAG, "Tried to setup non existing vpn profile."); + return; + } + setupVpnProfile = vpnProfile; + setupNClosestGateway.set(event.getIntExtra(Gateway.KEY_N_CLOSEST_GATEWAY, 0)); + Log.d(TAG, "bitmaskapp add state listener"); + VpnStatus.addStateListener(this); + + launchVPN(setupVpnProfile); + } + + private void launchVPN(VpnProfile vpnProfile) { + Intent intent = new Intent(context.getApplicationContext(), LaunchVPN.class); + intent.setAction(Intent.ACTION_MAIN); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(LaunchVPN.EXTRA_HIDELOG, true); + intent.putExtra(PROVIDER_PROFILE, vpnProfile); + intent.putExtra(Gateway.KEY_N_CLOSEST_GATEWAY, setupNClosestGateway.get()); + context.startActivity(intent); + } + + @Override + public void updateState(String state, String logmessage, int localizedResId, ConnectionStatus level) { + // VpnStatus.updateStateString("NOPROCESS", "No process running.", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED); + + Log.d(TAG, "vpn status: " + state + " - " + logmessage + " - " + level); + if (observedProfileFromVpnStatus == null || + setupVpnProfile == null) { + return; + } + if (!observedProfileFromVpnStatus.equals(setupVpnProfile.getUUIDString())) { + Log.d(TAG, "vpn profile to setup and observed profile currently is used differ: " + setupVpnProfile.getUUIDString() + " vs. " + observedProfileFromVpnStatus); + return; + } + + if (ConnectionStatus.LEVEL_STOPPING == level) { + finishGatewaySetup(false); + } else if ("CONNECTRETRY".equals(state) && LEVEL_CONNECTING_NO_SERVER_REPLY_YET.equals(level)) { + Log.d(TAG, "trying gateway: " + setupVpnProfile.getName()); + if (TIMEOUT.equals(logmessage)) { + Log.e(TAG, "Timeout reached! Try next gateway!"); + VpnStatus.logError("Timeout reached! Try next gateway!"); + selectNextGateway(); + return; + } + int current = reconnectTry.get(); + reconnectTry.set(current + 1); + } else if ("NOPROCESS".equals(state) && LEVEL_NOTCONNECTED == level) { + //?? + } else if ("CONNECTED".equals(state)) { + //saveLastProfile(context.getApplicationContext(), setupVpnProfile.getUUIDString()); + Provider provider = ProviderObservable.getInstance().getCurrentProvider(); + if (setupNClosestGateway.get() > 0 || provider.shouldUpdateEipServiceJson()) { + //setupNClostestGateway > 0: at least one failed gateway -> did the provider change it's gateways? + ProviderAPICommand.execute(context, ProviderAPI.DOWNLOAD_SERVICE_JSON, provider); + } + + if (shouldCheckAppUpdate()) { + DownloadServiceCommand.execute(context, CHECK_VERSION_FILE); + } + finishGatewaySetup(false); + } else if ("TCP_CONNECT".equals(state)) { + changingGateway.set(false); + } + } + + private boolean shouldCheckAppUpdate() { + return System.currentTimeMillis() - PreferenceHelper.getLastAppUpdateCheck(context) >= UPDATE_CHECK_TIMEOUT; + } + + private void selectNextGateway() { + changingGateway.set(true); + reconnectTry.set(0); + EipCommand.startVPN(context.getApplicationContext(), false, setupNClosestGateway.get() + 1); + } + + private void finishGatewaySetup(boolean changingGateway) { + VpnStatus.removeStateListener(this); + setupVpnProfile = null; + setupNClosestGateway.set(0); + observedProfileFromVpnStatus = null; + this.changingGateway.set(changingGateway); + this.reconnectTry.set(0); + } + + /** + * gets called as soon as a new VPN is about to launch + * + * @param uuid + */ + @Override + public void setConnectedVPN(String uuid) { + observedProfileFromVpnStatus = uuid; + } + + @Override + public void newLog(LogItem logItem) { + if (logItem.getLogLevel() == VpnStatus.LogLevel.ERROR) { + switch (logItem.getErrorType()) { + case SHAPESHIFTER: + VpnProfile profile = VpnStatus.getLastConnectedVpnProfile(); + if (profile == null) { + EipCommand.startVPN(context.getApplicationContext(), false, 0); + } else { + GatewaysManager gatewaysManager = new GatewaysManager(context.getApplicationContext()); + int position = gatewaysManager.getPosition(profile); + setupNClosestGateway.set(position >= 0 ? position : 0); + selectNextGateway(); + } + break; + default: + break; + + } + } + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java index f3eea415..1df54e6e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java @@ -32,16 +32,16 @@ import java.util.Set; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ConfigParser; import de.blinkt.openvpn.core.connection.Connection; -import se.leap.bitmaskclient.utils.PreferenceHelper; - -import static se.leap.bitmaskclient.Constants.HOST; -import static se.leap.bitmaskclient.Constants.IP_ADDRESS; -import static se.leap.bitmaskclient.Constants.LOCATION; -import static se.leap.bitmaskclient.Constants.LOCATIONS; -import static se.leap.bitmaskclient.Constants.NAME; -import static se.leap.bitmaskclient.Constants.OPENVPN_CONFIGURATION; -import static se.leap.bitmaskclient.Constants.TIMEZONE; -import static se.leap.bitmaskclient.Constants.VERSION; +import se.leap.bitmaskclient.base.utils.PreferenceHelper; + +import static se.leap.bitmaskclient.base.models.Constants.HOST; +import static se.leap.bitmaskclient.base.models.Constants.IP_ADDRESS; +import static se.leap.bitmaskclient.base.models.Constants.LOCATION; +import static se.leap.bitmaskclient.base.models.Constants.LOCATIONS; +import static se.leap.bitmaskclient.base.models.Constants.NAME; +import static se.leap.bitmaskclient.base.models.Constants.OPENVPN_CONFIGURATION; +import static se.leap.bitmaskclient.base.models.Constants.TIMEZONE; +import static se.leap.bitmaskclient.base.models.Constants.VERSION; /** * Gateway provides objects defining gateways and their metadata. diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java index 0ba0f207..33fd3c21 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java @@ -8,7 +8,7 @@ import java.util.Map; import java.util.Set; import java.util.TreeMap; -import static se.leap.bitmaskclient.utils.ConfigHelper.getCurrentTimezone; +import static se.leap.bitmaskclient.base.utils.ConfigHelper.getCurrentTimezone; public class GatewaySelector { private final static String TAG = GatewaySelector.class.getSimpleName(); diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java index 354fd9a3..a5d4c416 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java @@ -35,15 +35,15 @@ import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ConfigParser; import de.blinkt.openvpn.core.VpnStatus; import de.blinkt.openvpn.core.connection.Connection; -import se.leap.bitmaskclient.Provider; -import se.leap.bitmaskclient.ProviderObservable; +import se.leap.bitmaskclient.base.models.Provider; +import se.leap.bitmaskclient.base.models.ProviderObservable; 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.Constants.GATEWAYS; -import static se.leap.bitmaskclient.Constants.PROVIDER_PRIVATE_KEY; -import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE; -import static se.leap.bitmaskclient.utils.PreferenceHelper.getUsePluggableTransports; +import static se.leap.bitmaskclient.base.models.Constants.GATEWAYS; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUsePluggableTransports; /** * @author parmegv diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java index 9a3c8f85..e6905448 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnLauncher.java @@ -6,7 +6,7 @@ import android.net.VpnService; import android.os.Build; import android.os.Bundle; -import static se.leap.bitmaskclient.Constants.EIP_ACTION_START_BLOCKING_VPN; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START_BLOCKING_VPN; public class VoidVpnLauncher extends Activity { 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 78deea0b..77038492 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java @@ -33,14 +33,13 @@ import java.util.Observer; import de.blinkt.openvpn.core.ConnectionStatus; import de.blinkt.openvpn.core.VpnStatus; import se.leap.bitmaskclient.R; -import se.leap.bitmaskclient.VpnNotificationManager; - -import static se.leap.bitmaskclient.Constants.EIP_ACTION_START_ALWAYS_ON_VPN; -import static se.leap.bitmaskclient.Constants.EIP_ACTION_START_BLOCKING_VPN; -import static se.leap.bitmaskclient.Constants.EIP_ACTION_STOP_BLOCKING_VPN; -import static se.leap.bitmaskclient.Constants.EIP_IS_ALWAYS_ON; -import static se.leap.bitmaskclient.Constants.SHARED_PREFERENCES; -import static se.leap.bitmaskclient.utils.ConfigHelper.getProviderFormattedString; + +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; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_STOP_BLOCKING_VPN; +import static se.leap.bitmaskclient.base.models.Constants.EIP_IS_ALWAYS_ON; +import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; +import static se.leap.bitmaskclient.base.utils.ConfigHelper.getProviderFormattedString; public class VoidVpnService extends VpnService implements Observer, VpnNotificationManager.VpnServiceCallback { diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java index 83904729..c747b731 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnCertificateValidator.java @@ -22,7 +22,7 @@ import java.security.cert.X509Certificate; import java.util.Calendar; import java.util.Date; -import se.leap.bitmaskclient.utils.ConfigHelper; +import se.leap.bitmaskclient.base.utils.ConfigHelper; public class VpnCertificateValidator { public final static String TAG = VpnCertificateValidator.class.getSimpleName(); diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java index 08e219c7..51069d6d 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -30,21 +30,21 @@ import java.util.Iterator; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ConfigParser; import de.blinkt.openvpn.core.connection.Connection; -import se.leap.bitmaskclient.Provider; +import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.pluggableTransports.Obfs4Options; 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.Constants.CAPABILITIES; -import static se.leap.bitmaskclient.Constants.IP_ADDRESS; -import static se.leap.bitmaskclient.Constants.OPTIONS; -import static se.leap.bitmaskclient.Constants.PORTS; -import static se.leap.bitmaskclient.Constants.PROTOCOLS; -import static se.leap.bitmaskclient.Constants.PROVIDER_PRIVATE_KEY; -import static se.leap.bitmaskclient.Constants.PROVIDER_VPN_CERTIFICATE; -import static se.leap.bitmaskclient.Constants.REMOTE; -import static se.leap.bitmaskclient.Constants.TRANSPORT; -import static se.leap.bitmaskclient.Constants.TYPE; +import static se.leap.bitmaskclient.base.models.Constants.CAPABILITIES; +import static se.leap.bitmaskclient.base.models.Constants.IP_ADDRESS; +import static se.leap.bitmaskclient.base.models.Constants.OPTIONS; +import static se.leap.bitmaskclient.base.models.Constants.PORTS; +import static se.leap.bitmaskclient.base.models.Constants.PROTOCOLS; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; +import static se.leap.bitmaskclient.base.models.Constants.REMOTE; +import static se.leap.bitmaskclient.base.models.Constants.TRANSPORT; +import static se.leap.bitmaskclient.base.models.Constants.TYPE; import static se.leap.bitmaskclient.pluggableTransports.Dispatcher.DISPATCHER_IP; import static se.leap.bitmaskclient.pluggableTransports.Dispatcher.DISPATCHER_PORT; diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnNotificationManager.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnNotificationManager.java new file mode 100644 index 00000000..b3ed5394 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnNotificationManager.java @@ -0,0 +1,355 @@ +/** + * Copyright (c) 2018 LEAP Encryption Access Project and contributers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package se.leap.bitmaskclient.eip; + +import android.annotation.TargetApi; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Build; +import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.core.app.NotificationCompat; +import androidx.core.app.NotificationManagerCompat; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.TextUtils; +import android.text.style.StyleSpan; +import android.widget.RemoteViews; + +import de.blinkt.openvpn.LaunchVPN; +import de.blinkt.openvpn.core.ConnectionStatus; +import de.blinkt.openvpn.core.OpenVPNService; +import se.leap.bitmaskclient.base.MainActivity; +import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.base.StartActivity; + +import static android.os.Build.VERSION_CODES.O; +import static androidx.core.app.NotificationCompat.PRIORITY_HIGH; +import static androidx.core.app.NotificationCompat.PRIORITY_MAX; +import static androidx.core.app.NotificationCompat.PRIORITY_MIN; +import static android.text.TextUtils.isEmpty; +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.models.Constants.ASK_TO_CANCEL_VPN; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_STOP_BLOCKING_VPN; +import static se.leap.bitmaskclient.base.MainActivity.ACTION_SHOW_VPN_FRAGMENT; + +/** + * Created by cyberta on 14.01.18. + */ + +public class VpnNotificationManager { + + Context context; + private VpnServiceCallback vpnServiceCallback; + private NotificationManager notificationManager; + private NotificationManagerCompat compatNotificationManager; + private String[] notificationChannels = { + OpenVPNService.NOTIFICATION_CHANNEL_NEWSTATUS_ID, + OpenVPNService.NOTIFICATION_CHANNEL_BG_ID, + VoidVpnService.NOTIFICATION_CHANNEL_NEWSTATUS_ID}; + private String lastNotificationChannel = ""; + + public interface VpnServiceCallback { + void onNotificationBuild(int notificationId, Notification notification); + void onNotificationStop(); + } + + public VpnNotificationManager(@NonNull Context context, @NonNull VpnServiceCallback vpnServiceCallback) { + this.context = context; + notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + compatNotificationManager = NotificationManagerCompat.from(context); + this.vpnServiceCallback = vpnServiceCallback; + } + + public void buildVoidVpnNotification(final String msg, String tickerText, ConnectionStatus status) { + //TODO: implement extra Dashboard.ACTION_ASK_TO_CANCEL_BLOCKING_VPN + NotificationCompat.Action.Builder actionBuilder = new NotificationCompat.Action.Builder(R.drawable.ic_menu_close_clear_cancel, + context.getString(R.string.vpn_button_turn_off_blocking), getStopVoidVpnIntent()); + + buildVpnNotification( + context.getString(R.string.void_vpn_title), + msg, + null, + tickerText, + status, + VoidVpnService.NOTIFICATION_CHANNEL_NEWSTATUS_ID, + PRIORITY_MAX, + 0, + getMainActivityIntent(), + actionBuilder.build()); + } + + public void stopNotifications(String notificationChannelNewstatusId) { + vpnServiceCallback.onNotificationStop(); + compatNotificationManager.cancel(notificationChannelNewstatusId.hashCode()); + } + + public void deleteNotificationChannel(String notificationChannel) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && + notificationManager.getNotificationChannel(notificationChannel) != null) { + notificationManager.deleteNotificationChannel(notificationChannel); + } + } + + /** + * @param msg + * @param tickerText + * @param status + * @param when + */ + public void buildOpenVpnNotification(String profileName, boolean isObfuscated, String msg, String tickerText, ConnectionStatus status, long when, String notificationChannelNewstatusId) { + String cancelString; + CharSequence bigmessage = null; + String ghostIcon = new String(Character.toChars(0x1f309)); + + switch (status) { + // show cancel if no connection + case LEVEL_START: + case LEVEL_NONETWORK: + case LEVEL_CONNECTING_SERVER_REPLIED: + case LEVEL_CONNECTING_NO_SERVER_REPLY_YET: + cancelString = context.getString(R.string.cancel); + if (isObfuscated && Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { + Spannable spannable = new SpannableString(context.getString(R.string.obfuscated_connection_try)); + spannable.setSpan(new StyleSpan(Typeface.ITALIC), 0, spannable.length() -1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + bigmessage = TextUtils.concat(spannable, " " + ghostIcon + "\n" + msg); + } + break; + + // show disconnect if connection exists + case LEVEL_CONNECTED: + if (isObfuscated && Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { + Spannable spannable = new SpannableString(context.getString(R.string.obfuscated_connection)); + spannable.setSpan(new StyleSpan(Typeface.ITALIC), 0, spannable.length() -1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + bigmessage = TextUtils.concat(spannable, " " + ghostIcon + "\n" + msg); + } + default: + cancelString = context.getString(R.string.cancel_connection); + } + + if (isObfuscated) { + msg = ghostIcon + " " + msg; + } + + NotificationCompat.Action.Builder actionBuilder = new NotificationCompat.Action. + Builder(R.drawable.ic_menu_close_clear_cancel, cancelString, getDisconnectIntent()); + String title; + String appName = context.getString(R.string.app_name); + if (isEmpty(profileName)) { + title = appName; + } else { + title = context.getString(R.string.notifcation_title_bitmask, appName, profileName); + } + + PendingIntent contentIntent; + if (status == LEVEL_WAITING_FOR_USER_INPUT) + contentIntent = getUserInputIntent(msg); + else + contentIntent = getMainActivityIntent(); + + int priority; + if (OpenVPNService.NOTIFICATION_CHANNEL_NEWSTATUS_ID.equals(notificationChannelNewstatusId)) { + priority = PRIORITY_HIGH; + } else { + // background channel + priority = PRIORITY_MIN; + } + + buildVpnNotification( + title, + msg, + bigmessage, + tickerText, + status, + notificationChannelNewstatusId, + priority, + when, + contentIntent, + actionBuilder.build()); + } + + + @TargetApi(O) + public void createVoidVpnNotificationChannel() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { + return; + } + + // Connection status change messages + CharSequence name = context.getString(R.string.channel_name_status); + NotificationChannel mChannel = new NotificationChannel(VoidVpnService.NOTIFICATION_CHANNEL_NEWSTATUS_ID, + name, NotificationManager.IMPORTANCE_DEFAULT); + + mChannel.setDescription(context.getString(R.string.channel_description_status)); + mChannel.enableLights(true); + + mChannel.setLightColor(Color.BLUE); + mChannel.setSound(null, null); + notificationManager.createNotificationChannel(mChannel); + } + + @TargetApi(O) + public void createOpenVpnNotificationChannel() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { + return; + } + + // Background message + CharSequence name = context.getString(R.string.channel_name_background); + NotificationChannel mChannel = new NotificationChannel(OpenVPNService.NOTIFICATION_CHANNEL_BG_ID, + name, NotificationManager.IMPORTANCE_MIN); + + mChannel.setDescription(context.getString(R.string.channel_description_background)); + mChannel.enableLights(false); + + mChannel.setLightColor(Color.DKGRAY); + notificationManager.createNotificationChannel(mChannel); + + // Connection status change messages + name = context.getString(R.string.channel_name_status); + mChannel = new NotificationChannel(OpenVPNService.NOTIFICATION_CHANNEL_NEWSTATUS_ID, + name, NotificationManager.IMPORTANCE_DEFAULT); + + + mChannel.setDescription(context.getString(R.string.channel_description_status)); + mChannel.enableLights(true); + + mChannel.setLightColor(Color.BLUE); + mChannel.setSound(null, null); + notificationManager.createNotificationChannel(mChannel); + } + + /** + * @return a custom remote view for notifications for API 16 - 19 + */ + private RemoteViews getKitkatCustomRemoteView(ConnectionStatus status, String title, String message) { + int iconResource = getIconByConnectionStatus(status); + RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.v_custom_notification); + remoteViews.setImageViewResource(R.id.image_icon, iconResource); + remoteViews.setTextViewText(R.id.message, message); + remoteViews.setTextViewText(R.id.title, title); + + return remoteViews; + } + + private void buildVpnNotification(String title, String message, CharSequence bigMessage, String tickerText, ConnectionStatus status, String notificationChannelNewstatusId, int priority, long when, PendingIntent contentIntent, NotificationCompat.Action notificationAction) { + NotificationCompat.Builder nCompatBuilder = new NotificationCompat.Builder(context, notificationChannelNewstatusId); + int icon = getIconByConnectionStatus(status); + + // this is a workaround to avoid confusion between the Android's system vpn notification + // showing a filled out key icon and the bitmask icon indicating a different state. + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT && + notificationChannelNewstatusId.equals(OpenVPNService.NOTIFICATION_CHANNEL_NEWSTATUS_ID)) { + if (status != LEVEL_NONETWORK) { + // removes the icon from the system status bar + icon = android.R.color.transparent; + // adds the icon to the notification in the notification drawer + nCompatBuilder.setContent(getKitkatCustomRemoteView(status, title, message)); + } + } else { + nCompatBuilder.setStyle(new NotificationCompat.BigTextStyle(). + setBigContentTitle(title). + bigText(bigMessage)); + } + nCompatBuilder.addAction(notificationAction); + nCompatBuilder.setContentTitle(title); + nCompatBuilder.setCategory(NotificationCompat.CATEGORY_SERVICE); + nCompatBuilder.setLocalOnly(true); + nCompatBuilder.setContentText(message); + nCompatBuilder.setOnlyAlertOnce(true); + nCompatBuilder.setSmallIcon(icon); + nCompatBuilder.setPriority(priority); + nCompatBuilder.setOngoing(true); + nCompatBuilder.setUsesChronometer(true); + nCompatBuilder.setWhen(when); + nCompatBuilder.setContentIntent(contentIntent); + if (!isEmpty(tickerText)) { + nCompatBuilder.setTicker(tickerText); + } + + Notification notification = nCompatBuilder.build(); + int notificationId = notificationChannelNewstatusId.hashCode(); + + if (!notificationChannelNewstatusId.equals(lastNotificationChannel)) { + // Cancel old notification + for (String channel : notificationChannels) { + stopNotifications(channel); + } + } + + compatNotificationManager.notify(notificationId, notification); + vpnServiceCallback.onNotificationBuild(notificationId, notification); + lastNotificationChannel = notificationChannelNewstatusId; + } + + private PendingIntent getMainActivityIntent() { + Intent startActivity = new Intent(context, StartActivity.class); + return PendingIntent.getActivity(context, 0, startActivity, PendingIntent.FLAG_CANCEL_CURRENT); + } + + private PendingIntent getStopVoidVpnIntent() { + Intent stopVoidVpnIntent = new Intent (context, VoidVpnService.class); + stopVoidVpnIntent.setAction(EIP_ACTION_STOP_BLOCKING_VPN); + return PendingIntent.getService(context, 0, stopVoidVpnIntent, PendingIntent.FLAG_CANCEL_CURRENT); + } + + private PendingIntent getDisconnectIntent() { + Intent disconnectVPN = new Intent(context, MainActivity.class); + disconnectVPN.setAction(ACTION_SHOW_VPN_FRAGMENT); + disconnectVPN.putExtra(ASK_TO_CANCEL_VPN, true); + disconnectVPN.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + return PendingIntent.getActivity(context, 0, disconnectVPN, PendingIntent.FLAG_CANCEL_CURRENT); + } + + private PendingIntent getUserInputIntent(String needed) { + Intent intent = new Intent(context, LaunchVPN.class); + intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + intent.putExtra("need", needed); + Bundle b = new Bundle(); + b.putString("need", needed); + PendingIntent pIntent = PendingIntent.getActivity(context, 12, intent, 0); + return pIntent; + } + + private int getIconByConnectionStatus(ConnectionStatus level) { + switch (level) { + case LEVEL_CONNECTED: + return R.drawable.ic_stat_vpn; + case LEVEL_AUTH_FAILED: + case LEVEL_NONETWORK: + case LEVEL_NOTCONNECTED: + return R.drawable.ic_stat_vpn_offline; + case LEVEL_CONNECTING_NO_SERVER_REPLY_YET: + case LEVEL_WAITING_FOR_USER_INPUT: + case LEVEL_CONNECTING_SERVER_REPLIED: + return R.drawable.ic_stat_vpn_outline; + case LEVEL_BLOCKING: + return R.drawable.ic_stat_vpn_blocking; + case UNKNOWN_LEVEL: + default: + return R.drawable.ic_stat_vpn_offline; + } + } + +} |