diff --git a/app/build.gradle b/app/build.gradle index 28f80bdc8..ed6e7efed 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -247,8 +247,8 @@ dependencies { fullImplementation 'com.github.kirich1409:viewbindingpropertydelegate-noreflection:1.5.9' // from: https://jitpack.io/#celzero/firestack - download 'com.github.celzero:firestack:602a1e456d@aar' - implementation 'com.github.celzero:firestack:602a1e456d@aar' + download 'com.github.celzero:firestack:99521f3ca9@aar' + implementation 'com.github.celzero:firestack:99521f3ca9@aar' // Work manager implementation('androidx.work:work-runtime-ktx:2.9.0') { diff --git a/app/src/full/java/com/celzero/bravedns/adapter/ConnectionTrackerAdapter.kt b/app/src/full/java/com/celzero/bravedns/adapter/ConnectionTrackerAdapter.kt index 35eba7419..8799966b1 100644 --- a/app/src/full/java/com/celzero/bravedns/adapter/ConnectionTrackerAdapter.kt +++ b/app/src/full/java/com/celzero/bravedns/adapter/ConnectionTrackerAdapter.kt @@ -242,10 +242,13 @@ class ConnectionTrackerAdapter(private val context: Context) : hasMinSummary = true } else { b.connectionDataUsage.text = "" + b.connectionDuration.text ="" } if (connType.isMetered()) { b.connectionDelay.text = context.getString(R.string.symbol_currency) hasMinSummary = true + } else { + b.connectionDelay.text = "" } if (isConnectionProxied(ct.blockedByRule, ct.proxyDetails)) { diff --git a/app/src/full/java/com/celzero/bravedns/adapter/OneWgConfigAdapter.kt b/app/src/full/java/com/celzero/bravedns/adapter/OneWgConfigAdapter.kt index e690b3039..997ca98a6 100644 --- a/app/src/full/java/com/celzero/bravedns/adapter/OneWgConfigAdapter.kt +++ b/app/src/full/java/com/celzero/bravedns/adapter/OneWgConfigAdapter.kt @@ -114,6 +114,7 @@ class OneWgConfigAdapter(private val context: Context, private val listener: Dns b.interfaceDetailCard.strokeWidth = 0 b.interfaceAppsCount.visibility = View.GONE b.protocolInfoChipGroup.visibility = View.GONE + b.interfaceActiveLayout.visibility = View.GONE b.oneWgCheck.isChecked = false b.interfaceStatus.text = context.getString(R.string.lbl_disabled).replaceFirstChar(Char::titlecase) @@ -187,18 +188,24 @@ class OneWgConfigAdapter(private val context: Context, private val listener: Dns private fun updateStatusUi(config: WgConfigFiles, statusId: Long?, stats: Stats?) { if (config.isActive) { - b.interfaceDetailCard.strokeColor = fetchColor(context, R.color.accentGood) b.interfaceDetailCard.strokeWidth = 2 b.oneWgCheck.isChecked = true b.interfaceAppsCount.visibility = View.VISIBLE b.interfaceAppsCount.text = context.getString(R.string.one_wg_apps_added) val status: String + val handShakeTime = getHandshakeTime(stats) if (statusId != null) { - val resId = UIUtils.getProxyStatusStringRes(statusId) + var resId = UIUtils.getProxyStatusStringRes(statusId) // change the color based on the status if (statusId == Backend.TOK) { - b.interfaceDetailCard.strokeColor = - fetchColor(context, R.attr.chipTextPositive) + if (stats?.lastOK == 0L) { + b.interfaceDetailCard.strokeColor = + fetchColor(context, R.attr.chipTextNeutral) + resId = R.string.status_waiting + } else { + b.interfaceDetailCard.strokeColor = + fetchColor(context, R.attr.accentGood) + } // cancel the job, as the status is connected statusCheckJob?.cancel() } else if (statusId == Backend.TUP || statusId == Backend.TZZ) { @@ -208,7 +215,16 @@ class OneWgConfigAdapter(private val context: Context, private val listener: Dns b.interfaceDetailCard.strokeColor = fetchColor(context, R.attr.chipTextNegative) } - status = context.getString(resId).replaceFirstChar(Char::titlecase) + status = + if (stats?.lastOK == 0L) { + context.getString(resId).replaceFirstChar(Char::titlecase) + } else { + context.getString( + R.string.about_version_install_source, + context.getString(resId).replaceFirstChar(Char::titlecase), + handShakeTime + ) + } } else { b.interfaceDetailCard.strokeColor = fetchColor(context, R.attr.chipTextNegative) b.interfaceDetailCard.strokeWidth = 2 @@ -219,6 +235,7 @@ class OneWgConfigAdapter(private val context: Context, private val listener: Dns b.interfaceActiveLayout.visibility = View.VISIBLE val rxtx = getRxTx(stats) val time = getUpTime(stats) + if (time.isNotEmpty()) { val t = context.getString(R.string.logs_card_duration, time) b.interfaceActiveUptime.text = @@ -248,8 +265,8 @@ class OneWgConfigAdapter(private val context: Context, private val listener: Dns val now = System.currentTimeMillis() // returns a string describing 'time' as a time relative to 'now' return DateUtils.getRelativeTimeSpanString( - now, stats.since, + now, DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE ) @@ -270,6 +287,23 @@ class OneWgConfigAdapter(private val context: Context, private val listener: Dns return context.getString(R.string.two_argument_space, rx, tx) } + private fun getHandshakeTime(stats: Stats?): CharSequence { + if (stats == null) { + return "" + } + if (stats.lastOK == 0L) { + return "" + } + val now = System.currentTimeMillis() + // returns a string describing 'time' as a time relative to 'now' + return DateUtils.getRelativeTimeSpanString( + stats.lastOK, + now, + DateUtils.MINUTE_IN_MILLIS, + DateUtils.FORMAT_ABBREV_RELATIVE + ) + } + fun setupClickListeners(config: WgConfigFiles) { b.interfaceDetailCard.setOnClickListener { launchConfigDetail(config.id) } diff --git a/app/src/full/java/com/celzero/bravedns/adapter/WgConfigAdapter.kt b/app/src/full/java/com/celzero/bravedns/adapter/WgConfigAdapter.kt index e99cc667b..741003906 100644 --- a/app/src/full/java/com/celzero/bravedns/adapter/WgConfigAdapter.kt +++ b/app/src/full/java/com/celzero/bravedns/adapter/WgConfigAdapter.kt @@ -40,11 +40,11 @@ import com.celzero.bravedns.ui.activity.WgConfigDetailActivity import com.celzero.bravedns.ui.activity.WgConfigEditorActivity.Companion.INTENT_EXTRA_WG_ID import com.celzero.bravedns.util.UIUtils import com.celzero.bravedns.util.Utilities +import java.util.concurrent.ConcurrentHashMap import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch -import java.util.concurrent.ConcurrentHashMap class WgConfigAdapter(private val context: Context) : PagingDataAdapter(DIFF_CALLBACK) { @@ -127,6 +127,7 @@ class WgConfigAdapter(private val context: Context) : // if lockdown is enabled, then show the lockdown card even if config is disabled if (config.isLockdown) { b.protocolInfoChipGroup.visibility = View.GONE + b.interfaceActiveLayout.visibility = View.GONE b.interfaceConfigStatus.text = context.getString(R.string.lbl_disabled).replaceFirstChar(Char::titlecase) val id = ProxyManager.ID_WG_BASE + config.id @@ -135,6 +136,7 @@ class WgConfigAdapter(private val context: Context) : } else { b.interfaceStatus.visibility = View.GONE b.interfaceAppsCount.visibility = View.GONE + b.interfaceActiveLayout.visibility = View.GONE b.interfaceDetailCard.strokeColor = UIUtils.fetchColor(context, R.attr.background) b.interfaceDetailCard.strokeWidth = 0 b.interfaceSwitch.isChecked = false @@ -257,6 +259,7 @@ class WgConfigAdapter(private val context: Context) : if (!config.isActive) { // no need to update the apps count if the config is disabled b.interfaceAppsCount.visibility = View.GONE + b.interfaceActiveLayout.visibility = View.GONE return } @@ -281,6 +284,7 @@ class WgConfigAdapter(private val context: Context) : b.interfaceActiveLayout.visibility = View.VISIBLE val time = getUpTime(stats) val rxtx = getRxTx(stats) + val handShakeTime = getHandshakeTime(stats) if (time.isNotEmpty()) { val t = context.getString(R.string.logs_card_duration, time) b.interfaceActiveUptime.text = @@ -294,25 +298,47 @@ class WgConfigAdapter(private val context: Context) : } b.interfaceActiveRxTx.text = rxtx if (statusId != null) { - val resId = UIUtils.getProxyStatusStringRes(statusId) + var resId = UIUtils.getProxyStatusStringRes(statusId) // change the color based on the status if (statusId == Backend.TOK) { - b.interfaceDetailCard.strokeColor = - UIUtils.fetchColor(context, R.attr.accentGood) + // if the lastOK is 0, then the handshake is not yet completed + // so show the status as waiting + if (stats?.lastOK == 0L) { + b.interfaceDetailCard.strokeColor = + UIUtils.fetchColor(context, R.attr.chipTextNeutral) + resId = R.string.status_waiting + } else { + b.interfaceDetailCard.strokeColor = + UIUtils.fetchColor(context, R.attr.accentGood) + } cancelJobIfAny(config.id) - } else if (statusId == Backend.TUP || statusId == Backend.TZZ) { + } else if ( + statusId == Backend.TUP || + statusId == Backend.TZZ || + statusId == Backend.TNT + ) { b.interfaceDetailCard.strokeColor = UIUtils.fetchColor(context, R.attr.chipTextNeutral) } else { b.interfaceDetailCard.strokeColor = UIUtils.fetchColor(context, R.attr.accentBad) } - status = context.getString(resId).replaceFirstChar(Char::titlecase) + status = + if (stats?.lastOK == 0L) { + context.getString(resId).replaceFirstChar(Char::titlecase) + } else { + context.getString( + R.string.about_version_install_source, + context.getString(resId).replaceFirstChar(Char::titlecase), + handShakeTime + ) + } } else { b.interfaceDetailCard.strokeColor = UIUtils.fetchColor(context, R.attr.accentBad) status = context.getString(R.string.status_waiting).replaceFirstChar(Char::titlecase) + b.interfaceActiveLayout.visibility = View.GONE } b.interfaceStatus.text = status } else { @@ -350,8 +376,25 @@ class WgConfigAdapter(private val context: Context) : val now = System.currentTimeMillis() // returns a string describing 'time' as a time relative to 'now' return DateUtils.getRelativeTimeSpanString( - now, stats.since, + now, + DateUtils.MINUTE_IN_MILLIS, + DateUtils.FORMAT_ABBREV_RELATIVE + ) + } + + private fun getHandshakeTime(stats: Stats?): CharSequence { + if (stats == null) { + return "" + } + if (stats.lastOK == 0L) { + return "" + } + val now = System.currentTimeMillis() + // returns a string describing 'time' as a time relative to 'now' + return DateUtils.getRelativeTimeSpanString( + stats.lastOK, + now, DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE ) diff --git a/app/src/full/java/com/celzero/bravedns/adapter/WgIncludeAppsAdapter.kt b/app/src/full/java/com/celzero/bravedns/adapter/WgIncludeAppsAdapter.kt index 23162f56f..4ecc80707 100644 --- a/app/src/full/java/com/celzero/bravedns/adapter/WgIncludeAppsAdapter.kt +++ b/app/src/full/java/com/celzero/bravedns/adapter/WgIncludeAppsAdapter.kt @@ -94,7 +94,6 @@ class WgIncludeAppsAdapter( fun update(mapping: ProxyApplicationMapping) { b.wgIncludeAppListApkLabelTv.text = mapping.appName - Logger.i(LOG_TAG_PROXY, "add ${mapping.appName} to ${mapping.proxyId} from $proxyId") if (mapping.proxyId == "") { b.wgIncludeAppAppDescTv.text = "" diff --git a/app/src/full/java/com/celzero/bravedns/service/ProxyManager.kt b/app/src/full/java/com/celzero/bravedns/service/ProxyManager.kt index 0130bea0c..564bb687b 100644 --- a/app/src/full/java/com/celzero/bravedns/service/ProxyManager.kt +++ b/app/src/full/java/com/celzero/bravedns/service/ProxyManager.kt @@ -188,7 +188,7 @@ object ProxyManager : KoinComponent { } suspend fun deleteApps(m: Collection) { - m.forEach { deleteApp(it) } + m.forEach { deleteApp(it.uid, it.packageName) } } suspend fun addApps(m: Collection) { @@ -219,7 +219,10 @@ object ProxyManager : KoinComponent { } suspend fun addNewApp(appInfo: AppInfo?, proxyId: String = "", proxyName: String = "") { - if (appInfo == null) return + if (appInfo == null) { + Logger.e(LOG_TAG_PROXY, "AppInfo is null, cannot add to proxy") + return + } val pam = ProxyApplicationMapping( appInfo.uid, @@ -232,6 +235,7 @@ object ProxyManager : KoinComponent { val pamTuple = ProxyAppMapTuple(appInfo.uid, appInfo.packageName, proxyId) pamSet.add(pamTuple) db.insert(pam) + Logger.i(LOG_TAG_PROXY, "Adding app for mapping: ${pam.appName}, ${pam.uid}") } private fun deleteFromCache(pam: ProxyApplicationMapping) { @@ -242,15 +246,12 @@ object ProxyManager : KoinComponent { } } - suspend fun deleteApp(appInfo: AppInfo) { - return deleteApp(appInfo.uid, appInfo.packageName) - } - - suspend fun deleteApp(appInfoTuple: FirewallManager.AppInfoTuple) { - return deleteApp(appInfoTuple.uid, appInfoTuple.packageName) + suspend fun deleteAppMappingsByUid(uid: Int) { + val m = pamSet.filter { it.uid == uid } + m.forEach { deleteApp(it.uid, it.packageName) } } - suspend fun deleteApp(uid: Int, packageName: String) { + private suspend fun deleteApp(uid: Int, packageName: String) { val pam = ProxyApplicationMapping(uid, packageName, "", "", false, "") deleteFromCache(pam) db.deleteApp(pam) @@ -260,6 +261,7 @@ object ProxyManager : KoinComponent { suspend fun clear() { pamSet.clear() db.deleteAll() + Logger.d(LOG_TAG_PROXY, "Deleting all apps for mapping") } fun isAnyAppSelected(proxyId: String): Boolean { diff --git a/app/src/full/java/com/celzero/bravedns/service/WireguardManager.kt b/app/src/full/java/com/celzero/bravedns/service/WireguardManager.kt index a9b2ce044..04b6b1181 100644 --- a/app/src/full/java/com/celzero/bravedns/service/WireguardManager.kt +++ b/app/src/full/java/com/celzero/bravedns/service/WireguardManager.kt @@ -86,7 +86,12 @@ object WireguardManager : KoinComponent { mappings.forEach { val path = it.configPath val config = - EncryptedFileManager.readWireguardConfig(applicationContext, path) ?: return@forEach + EncryptedFileManager.readWireguardConfig(applicationContext, path) + if (config == null) { + Logger.e(LOG_TAG_PROXY, "error loading wg config: $path, deleting...") + db.deleteConfig(it.id) + return@forEach + } if (configs.none { i -> i.getId() == it.id }) { val c = Config.Builder() diff --git a/app/src/full/java/com/celzero/bravedns/util/UIUtils.kt b/app/src/full/java/com/celzero/bravedns/util/UIUtils.kt index 8b056b8df..a4a412a4f 100644 --- a/app/src/full/java/com/celzero/bravedns/util/UIUtils.kt +++ b/app/src/full/java/com/celzero/bravedns/util/UIUtils.kt @@ -98,6 +98,9 @@ object UIUtils { Backend.END -> { R.string.lbl_stopped } + Backend.TNT -> { + R.string.status_waiting + } else -> { R.string.rt_filter_parent_selected } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index edbb2492f..af40a67cd 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,8 +2,8 @@ + android:versionCode="39" + android:versionName="v055h"> diff --git a/app/src/main/java/com/celzero/bravedns/database/RefreshDatabase.kt b/app/src/main/java/com/celzero/bravedns/database/RefreshDatabase.kt index 93ee3b846..7bebe7116 100644 --- a/app/src/main/java/com/celzero/bravedns/database/RefreshDatabase.kt +++ b/app/src/main/java/com/celzero/bravedns/database/RefreshDatabase.kt @@ -55,13 +55,13 @@ import com.celzero.bravedns.util.Utilities.getActivityPendingIntent import com.celzero.bravedns.util.Utilities.isAtleastO import com.celzero.bravedns.util.Utilities.isAtleastT import com.celzero.bravedns.util.Utilities.isNonApp +import java.util.concurrent.TimeUnit +import kotlin.random.Random import kotlinx.coroutines.CoroutineName import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.launch -import java.util.concurrent.TimeUnit -import kotlin.random.Random class RefreshDatabase internal constructor( @@ -253,8 +253,7 @@ internal constructor( packagesToDelete.forEach { IpRulesManager.deleteRulesByUid(it.uid) DomainRulesManager.deleteRulesByUid(it.uid) - val appInfo = FirewallManager.getAppInfoByUid(it.uid) ?: return@forEach - ProxyManager.deleteApp(appInfo) + ProxyManager.deleteAppMappingsByUid(it.uid) } FirewallManager.deletePackages(packagesToDelete) } @@ -393,8 +392,12 @@ internal constructor( if (emptyAll) { ProxyManager.clear() trackedApps - .map { FirewallManager.getAppInfoByUid(it.uid) } + .map { FirewallManager.getAppInfoByPackage(it.packageName) } .forEach { ProxyManager.addNewApp(it) } // it may be null, esp for non-apps + Logger.i( + LOG_TAG_APP_DB, + "empty proxy mapping, trackedApps: ${trackedApps.size}, proxy mapping: ${ProxyManager.trackedApps().size}" + ) return } @@ -404,11 +407,13 @@ internal constructor( val pxm = ProxyManager.trackedApps() val del = findPackagesToDelete(pxm, trackedApps) val add = - findPackagesToAdd(pxm, trackedApps).map { FirewallManager.getAppInfoByUid(it.uid) } + findPackagesToAdd(pxm, trackedApps).map { + FirewallManager.getAppInfoByPackage(it.packageName) + } ProxyManager.deleteApps(del) ProxyManager.addApps(add) Logger.i( - "AppDatabase", + LOG_TAG_APP_DB, "refreshing proxy mapping, size: ${pxm.size}, trackedApps: ${trackedApps.size}" ) } diff --git a/app/src/main/java/com/celzero/bravedns/net/go/GoVpnAdapter.kt b/app/src/main/java/com/celzero/bravedns/net/go/GoVpnAdapter.kt index 719b23944..ece6260dc 100644 --- a/app/src/main/java/com/celzero/bravedns/net/go/GoVpnAdapter.kt +++ b/app/src/main/java/com/celzero/bravedns/net/go/GoVpnAdapter.kt @@ -805,7 +805,7 @@ class GoVpnAdapter : KoinComponent { Logger.i(LOG_TAG_VPN, "proxy stats($id): $stats") stats } catch (e: Exception) { - Logger.e(LOG_TAG_VPN, "error getting proxy stats($id): ${e.message}", e) + Logger.e(LOG_TAG_VPN, "error getting proxy stats($id): ${e.message}") null } } diff --git a/app/src/main/java/com/celzero/bravedns/service/BraveVPNService.kt b/app/src/main/java/com/celzero/bravedns/service/BraveVPNService.kt index 7390cf499..5632fe0e4 100644 --- a/app/src/main/java/com/celzero/bravedns/service/BraveVPNService.kt +++ b/app/src/main/java/com/celzero/bravedns/service/BraveVPNService.kt @@ -20,8 +20,9 @@ import Logger import Logger.LOG_TAG_VPN import android.app.ActivityManager import android.app.ForegroundServiceStartNotAllowedException -import android.app.ForegroundServiceTypeException +import android.app.InvalidForegroundServiceTypeException import android.app.KeyguardManager +import android.app.MissingForegroundServiceTypeException import android.app.Notification import android.app.NotificationChannel import android.app.NotificationManager @@ -89,6 +90,7 @@ import com.celzero.bravedns.util.UIUtils.getAccentColor import com.celzero.bravedns.util.Utilities import com.celzero.bravedns.util.Utilities.isAtleastO import com.celzero.bravedns.util.Utilities.isAtleastQ +import com.celzero.bravedns.util.Utilities.isAtleastS import com.celzero.bravedns.util.Utilities.isAtleastU import com.celzero.bravedns.util.Utilities.isMissingOrInvalidUid import com.celzero.bravedns.util.Utilities.isNetworkSame @@ -99,18 +101,6 @@ import inet.ipaddr.HostName import inet.ipaddr.IPAddressString import intra.Bridge import intra.SocketSummary -import kotlinx.coroutines.CoroutineName -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.MainScope -import kotlinx.coroutines.async -import kotlinx.coroutines.cancel -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withContext -import org.koin.android.ext.android.inject -import rnet.ServerSummary -import rnet.Tab import java.io.IOException import java.net.InetAddress import java.net.SocketException @@ -123,6 +113,18 @@ import java.util.concurrent.atomic.AtomicBoolean import kotlin.math.abs import kotlin.math.min import kotlin.random.Random +import kotlinx.coroutines.CoroutineName +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.async +import kotlinx.coroutines.cancel +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext +import org.koin.android.ext.android.inject +import rnet.ServerSummary +import rnet.Tab class BraveVPNService : VpnService(), ConnectionMonitor.NetworkListener, Bridge, OnSharedPreferenceChangeListener { @@ -1314,6 +1316,9 @@ class BraveVPNService : // startForeground should always be called within 5 secs of onStartCommand invocation // https://developer.android.com/guide/components/fg-service-types + // to log the exception type, wrap the call in different methods based on the API level + // TODO: can remove multiple startForegroundService calls if we decide to remove + // multiple catch blocks for API 31 and above if (isAtleastU()) { var ok = startForegroundService(FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED) if (!ok) { @@ -1326,7 +1331,12 @@ class BraveVPNService : return@ui } } else { - startForeground(SERVICE_ID, updateNotificationBuilder()) + val ok = startForegroundService() + if (!ok) { + Logger.i(LOG_TAG_VPN, "start service failed ( > U ), stopping service") + signalStopService(userInitiated = false) // notify and stop + return@ui + } } startOrbotAsyncIfNeeded() @@ -1391,13 +1401,15 @@ class BraveVPNService : serviceType ) return true - } catch (e: ForegroundServiceStartNotAllowedException) { + } catch (e: ForegroundServiceStartNotAllowedException) { // API 31 and above Logger.e(LOG_TAG_VPN, "startForeground failed, start not allowed exception", e) - } catch (e: ForegroundServiceTypeException) { - Logger.e(LOG_TAG_VPN, "startForeground failed, service type exception", e) - } catch (e: SecurityException) { + } catch (e: InvalidForegroundServiceTypeException) { // API 34 and above + Logger.e(LOG_TAG_VPN, "startForeground failed, invalid service type exception", e) + } catch (e: MissingForegroundServiceTypeException) { // API 34 and above + Logger.e(LOG_TAG_VPN, "startForeground failed, missing service type exception", e) + } catch (e: SecurityException) { // API 34 and above Logger.e(LOG_TAG_VPN, "startForeground failed, security exception", e) - } catch (e: IllegalArgumentException) { + } catch (e: IllegalArgumentException) { // API 34 and above Logger.e(LOG_TAG_VPN, "startForeground failed, illegal argument", e) } catch (e: Exception) { Logger.e(LOG_TAG_VPN, "startForeground failed", e) @@ -1405,6 +1417,27 @@ class BraveVPNService : return false } + private fun startForegroundService(): Boolean { + if (isAtleastS()) { + try { + startForeground(SERVICE_ID, updateNotificationBuilder()) + return true + } catch (e: ForegroundServiceStartNotAllowedException) { // API 31 and above + Logger.e(LOG_TAG_VPN, "startForeground failed, start not allowed exception", e) + } catch (e: Exception) { + Logger.e(LOG_TAG_VPN, "startForeground failed", e) + } + } else { + try { + startForeground(SERVICE_ID, updateNotificationBuilder()) + return true + } catch (e: Exception) { // no exception expected for API < 31 + Logger.e(LOG_TAG_VPN, "startForeground failed", e) + } + } + return false + } + private fun mtu(): Int { val overlayMtu = overlayNetworks.mtu val underlyingMtu = underlyingNetworks?.minMtu ?: VPN_INTERFACE_MTU diff --git a/gradle.properties b/gradle.properties index 575017810..e654a8a86 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,5 +24,5 @@ android.nonTransitiveRClass=true # Enable configuration cache org.gradle.unsafe.configuration-cache=true android.nonFinalResIds=true -# Version code for this module (38 for v055g) -VERSION_CODE=38 +# Version code for this module (39 for v055h) +VERSION_CODE=39