From cf6e6f355cc71e43c69f20716a7aa6fd0d6990ce Mon Sep 17 00:00:00 2001 From: cyBerta Date: Tue, 23 Feb 2021 01:14:28 +0100 Subject: some refactorings in VpnNotificationManager, start foreground service notification in onCreate already --- .../de/blinkt/openvpn/core/OpenVPNService.java | 42 +++--- .../se/leap/bitmaskclient/eip/VoidVpnService.java | 16 +- .../bitmaskclient/eip/VpnNotificationManager.java | 161 ++++++++++----------- 3 files changed, 105 insertions(+), 114 deletions(-) (limited to 'app') 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 2c1a65dc..1670c0be 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -24,12 +24,13 @@ import android.os.IBinder; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.RemoteException; -import androidx.annotation.RequiresApi; import android.system.OsConstants; import android.text.TextUtils; import android.util.Log; import android.widget.Toast; +import androidx.annotation.RequiresApi; + import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.net.Inet6Address; @@ -46,8 +47,8 @@ import de.blinkt.openvpn.core.connection.Connection; import de.blinkt.openvpn.core.connection.Obfs4Connection; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.eip.VpnNotificationManager; -import se.leap.bitmaskclient.pluggableTransports.Shapeshifter; import se.leap.bitmaskclient.firewall.FirewallManager; +import se.leap.bitmaskclient.pluggableTransports.Shapeshifter; import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_CONNECTED; import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT; @@ -61,7 +62,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac public static final String START_SERVICE_STICKY = "de.blinkt.openvpn.START_SERVICE_STICKY"; public static final String ALWAYS_SHOW_NOTIFICATION = "de.blinkt.openvpn.NOTIFICATION_ALWAYS_VISIBLE"; public static final String DISCONNECT_VPN = "de.blinkt.openvpn.DISCONNECT_VPN"; - public static final String NOTIFICATION_CHANNEL_BG_ID = "openvpn_bg"; public static final String NOTIFICATION_CHANNEL_NEWSTATUS_ID = "openvpn_newstat"; public static final String VPNSERVICE_TUN = "vpnservice-tun"; public final static String ORBOT_PACKAGE_NAME = "org.torproject.android"; @@ -280,6 +280,20 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac } + 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); + } + @Override public int onStartCommand(Intent intent, int flags, int startId) { @@ -524,8 +538,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac @Override public void onCreate() { super.onCreate(); - notificationManager = new VpnNotificationManager(this, this); - notificationManager.createOpenVpnNotificationChannel(); + notificationManager = new VpnNotificationManager(this); + startWithForegroundNotification(); firewallManager = new FirewallManager(this, true); } @@ -543,9 +557,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac // Just in case unregister for state VpnStatus.removeStateListener(this); VpnStatus.flushLog(); - notificationManager.deleteNotificationChannel(NOTIFICATION_CHANNEL_BG_ID); - notificationManager.deleteNotificationChannel(NOTIFICATION_CHANNEL_NEWSTATUS_ID); firewallManager.onDestroy(); + notificationManager.cancelAllNotifications(); } private String getTunConfigString() { @@ -1013,14 +1026,10 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac if (mProcessThread == null && !mNotificationAlwaysVisible) return; - String channel = NOTIFICATION_CHANNEL_NEWSTATUS_ID; // Display byte count only after being connected - if (level == LEVEL_CONNECTED) { mDisplayBytecount = true; mConnecttime = System.currentTimeMillis(); - if (!runningOnAndroidTV()) - channel = NOTIFICATION_CHANNEL_BG_ID; firewallManager.start(); } else { mDisplayBytecount = false; @@ -1033,7 +1042,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac VpnStatus.getLastCleanLogMessage(this), level, 0, - channel); + NOTIFICATION_CHANNEL_NEWSTATUS_ID); } @@ -1064,7 +1073,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac null, LEVEL_CONNECTED, mConnecttime, - NOTIFICATION_CHANNEL_BG_ID); + NOTIFICATION_CHANNEL_NEWSTATUS_ID); } } @@ -1108,7 +1117,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac getString(resid), LEVEL_WAITING_FOR_USER_INPUT, 0, - NOTIFICATION_CHANNEL_BG_ID); + NOTIFICATION_CHANNEL_NEWSTATUS_ID); } @@ -1117,11 +1126,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac startForeground(notificationId, notification); } - @Override - public void onNotificationStop() { - stopForeground(true); - } - public void trigger_url_open(String info) { /* String channel = NOTIFICATION_CHANNEL_USERREQ_ID; 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 77038492..0c46f8cd 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java @@ -58,7 +58,7 @@ public class VoidVpnService extends VpnService implements Observer, VpnNotificat super.onCreate(); eipStatus = EipStatus.getInstance(); eipStatus.addObserver(this); - notificationManager = new VpnNotificationManager(this, this); + notificationManager = new VpnNotificationManager(this); notificationManager.createVoidVpnNotificationChannel(); } @@ -100,13 +100,12 @@ public class VoidVpnService extends VpnService implements Observer, VpnNotificat } private void stop() { - notificationManager.stopNotifications(NOTIFICATION_CHANNEL_NEWSTATUS_ID); - notificationManager.deleteNotificationChannel(NOTIFICATION_CHANNEL_NEWSTATUS_ID); if (thread != null) { thread.interrupt(); } closeFd(); VpnStatus.updateStateString("NOPROCESS", "BLOCKING VPN STOPPED", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED); + stopForeground(true); } public static boolean isRunning() throws NullPointerException { @@ -185,9 +184,11 @@ public class VoidVpnService extends VpnService implements Observer, VpnNotificat notificationManager.buildVoidVpnNotification( blockingMessage, blockingMessage, - eipStatus.getLevel()); + eipStatus.getLevel(), + this + ); } else { - notificationManager.stopNotifications(NOTIFICATION_CHANNEL_NEWSTATUS_ID); + stopForeground(true); } } @@ -196,9 +197,4 @@ public class VoidVpnService extends VpnService implements Observer, VpnNotificat startForeground(notificationId, notification); } - @Override - public void onNotificationStop() { - stopForeground(true); - } - } 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 b3ed5394..6fd33352 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnNotificationManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnNotificationManager.java @@ -27,32 +27,35 @@ 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.util.Log; import android.widget.RemoteViews; +import androidx.annotation.NonNull; +import androidx.core.app.NotificationCompat; +import androidx.core.app.NotificationManagerCompat; + import de.blinkt.openvpn.LaunchVPN; import de.blinkt.openvpn.core.ConnectionStatus; import de.blinkt.openvpn.core.OpenVPNService; -import se.leap.bitmaskclient.base.MainActivity; +import de.blinkt.openvpn.core.VpnStatus; import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.base.MainActivity; import se.leap.bitmaskclient.base.StartActivity; import static android.os.Build.VERSION_CODES.O; -import static androidx.core.app.NotificationCompat.PRIORITY_HIGH; +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 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.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_STOP_BLOCKING_VPN; -import static se.leap.bitmaskclient.base.MainActivity.ACTION_SHOW_VPN_FRAGMENT; /** * Created by cyberta on 14.01.18. @@ -60,29 +63,20 @@ import static se.leap.bitmaskclient.base.MainActivity.ACTION_SHOW_VPN_FRAGMENT; public class VpnNotificationManager { + private static final String TAG = VpnNotificationManager.class.getSimpleName(); 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 = ""; + private final NotificationManagerCompat compatNotificationManager; public interface VpnServiceCallback { void onNotificationBuild(int notificationId, Notification notification); - void onNotificationStop(); } - public VpnNotificationManager(@NonNull Context context, @NonNull VpnServiceCallback vpnServiceCallback) { + public VpnNotificationManager(@NonNull Context context) { 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) { + public void buildVoidVpnNotification(final String msg, String tickerText, ConnectionStatus status, VpnServiceCallback callback) { //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()); @@ -97,28 +91,14 @@ public class VpnNotificationManager { PRIORITY_MAX, 0, getMainActivityIntent(), - actionBuilder.build()); - } - - public void stopNotifications(String notificationChannelNewstatusId) { - vpnServiceCallback.onNotificationStop(); - compatNotificationManager.cancel(notificationChannelNewstatusId.hashCode()); + actionBuilder.build(), + callback + ); } - 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) { + public void buildOpenVpnNotification(String profileName, boolean isObfuscated, String msg, + String tickerText, ConnectionStatus status, long when, + String notificationChannelNewstatusId, VpnServiceCallback vpnServiceCallback) { String cancelString; CharSequence bigmessage = null; String ghostIcon = new String(Character.toChars(0x1f309)); @@ -158,7 +138,7 @@ public class VpnNotificationManager { String appName = context.getString(R.string.app_name); if (isEmpty(profileName)) { title = appName; - } else { + } else { title = context.getString(R.string.notifcation_title_bitmask, appName, profileName); } @@ -170,7 +150,7 @@ public class VpnNotificationManager { int priority; if (OpenVPNService.NOTIFICATION_CHANNEL_NEWSTATUS_ID.equals(notificationChannelNewstatusId)) { - priority = PRIORITY_HIGH; + priority = PRIORITY_DEFAULT; } else { // background channel priority = PRIORITY_MIN; @@ -186,10 +166,19 @@ public class VpnNotificationManager { priority, when, contentIntent, - actionBuilder.build()); + actionBuilder.build(), + vpnServiceCallback); + } + + public void buildOpenVpnNotification(String profileName, boolean isObfuscated, String msg, String tickerText, ConnectionStatus status, long when, String notificationChannelNewstatusId) { + buildOpenVpnNotification(profileName, isObfuscated, msg, tickerText, status, when, notificationChannelNewstatusId, null); } + public void cancelAllNotifications() { + compatNotificationManager.cancelAll(); + } + @TargetApi(O) public void createVoidVpnNotificationChannel() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { @@ -197,16 +186,19 @@ public class VpnNotificationManager { } // 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); + NotificationChannel channel = compatNotificationManager.getNotificationChannel(VoidVpnService.NOTIFICATION_CHANNEL_NEWSTATUS_ID); + if (channel == null) { + CharSequence name = context.getString(R.string.channel_name_status); + channel = new NotificationChannel(VoidVpnService.NOTIFICATION_CHANNEL_NEWSTATUS_ID, + name, NotificationManager.IMPORTANCE_DEFAULT); + + channel.setDescription(context.getString(R.string.channel_description_status)); + channel.enableLights(true); + + channel.setLightColor(Color.BLUE); + channel.setSound(null, null); + compatNotificationManager.createNotificationChannel(channel); + } } @TargetApi(O) @@ -215,29 +207,20 @@ public class VpnNotificationManager { 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); + NotificationChannel channel = compatNotificationManager.getNotificationChannel(OpenVPNService.NOTIFICATION_CHANNEL_NEWSTATUS_ID); + if (channel == null) { + CharSequence name = context.getString(R.string.channel_name_status); + channel = new NotificationChannel(OpenVPNService.NOTIFICATION_CHANNEL_NEWSTATUS_ID, + name, NotificationManager.IMPORTANCE_DEFAULT); + + channel.setDescription(context.getString(R.string.channel_description_status)); + channel.enableLights(true); + + channel.setLightColor(Color.BLUE); + channel.setSound(null, null); + compatNotificationManager.createNotificationChannel(channel); + } } /** @@ -253,7 +236,21 @@ public class VpnNotificationManager { 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) { + 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) { NotificationCompat.Builder nCompatBuilder = new NotificationCompat.Builder(context, notificationChannelNewstatusId); int icon = getIconByConnectionStatus(status); @@ -291,16 +288,10 @@ public class VpnNotificationManager { 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; + if (vpnServiceCallback != null) { + vpnServiceCallback.onNotificationBuild(notificationId, notification); + } } private PendingIntent getMainActivityIntent() { -- cgit v1.2.3