From ca43c6e69ed7d9ad90bb5f1de981a065d2d89b47 Mon Sep 17 00:00:00 2001 From: albexk Date: Tue, 1 Oct 2024 20:21:56 +0300 Subject: [PATCH 1/9] Up Qt to 6.7.3 --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index d9138516..f9fb19a5 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -301,7 +301,7 @@ jobs: env: ANDROID_BUILD_PLATFORM: android-34 - QT_VERSION: 6.7.2 + QT_VERSION: 6.7.3 QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools' PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }} DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }} From 744b45476c60cd78a00a9b92efe8f818d11d7dcb Mon Sep 17 00:00:00 2001 From: albexk Date: Tue, 1 Oct 2024 20:23:06 +0300 Subject: [PATCH 2/9] Bump version to 4.8.2.0 --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fba4183c..1b8989a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR) set(PROJECT AmneziaVPN) -project(${PROJECT} VERSION 4.8.1.9 +project(${PROJECT} VERSION 4.8.2.0 DESCRIPTION "AmneziaVPN" HOMEPAGE_URL "https://amnezia.org/" ) @@ -11,7 +11,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d") set(RELEASE_DATE "${CURRENT_DATE}") set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH}) -set(APP_ANDROID_VERSION_CODE 65) +set(APP_ANDROID_VERSION_CODE 66) if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") set(MZ_PLATFORM_NAME "linux") From 4910dcfa96a60093397aafa53204fe9b90c47bea Mon Sep 17 00:00:00 2001 From: albexk Date: Wed, 2 Oct 2024 15:18:05 +0300 Subject: [PATCH 3/9] Set the maximum version of Androids to 7.1 (API 25) --- .github/workflows/deploy.yml | 2 +- client/android/AndroidManifest.xml | 6 +++ .../vpn/protocol/openvpn/OpenVpnClient.kt | 8 ---- .../protocolApi/src/main/kotlin/Protocol.kt | 16 +------ .../src/main/kotlin/ProtocolConfig.kt | 2 +- client/android/qt/build.gradle.kts | 2 +- .../src/org/amnezia/vpn/AmneziaActivity.kt | 28 +------------ .../src/org/amnezia/vpn/AmneziaTileService.kt | 42 ++----------------- .../src/org/amnezia/vpn/AmneziaVpnService.kt | 36 +--------------- .../org/amnezia/vpn/ServiceNotification.kt | 29 ++----------- .../src/org/amnezia/vpn/VpnRequestActivity.kt | 10 ++--- client/android/utils/src/main/kotlin/Log.kt | 17 ++------ .../utils/src/main/kotlin/net/NetworkState.kt | 37 ++-------------- .../utils/src/main/kotlin/net/TrafficStats.kt | 17 +++----- 14 files changed, 35 insertions(+), 217 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index f9fb19a5..f3ac2ff1 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -301,7 +301,7 @@ jobs: env: ANDROID_BUILD_PLATFORM: android-34 - QT_VERSION: 6.7.3 + QT_VERSION: 6.6.3 QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools' PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }} DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }} diff --git a/client/android/AndroidManifest.xml b/client/android/AndroidManifest.xml index 179def86..6d77f13c 100644 --- a/client/android/AndroidManifest.xml +++ b/client/android/AndroidManifest.xml @@ -3,10 +3,13 @@ + + @@ -67,6 +70,9 @@ android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --" /> + = Build.VERSION_CODES.Q) { - try { - configBuilder.setHttpProxy(ProxyInfo.buildDirectProxy(host, port)) - } catch (e: Exception) { - Log.e(TAG, "Could not set proxy: ${e.message}") - return false - } - } return true } diff --git a/client/android/protocolApi/src/main/kotlin/Protocol.kt b/client/android/protocolApi/src/main/kotlin/Protocol.kt index b5c382be..76900bf0 100644 --- a/client/android/protocolApi/src/main/kotlin/Protocol.kt +++ b/client/android/protocolApi/src/main/kotlin/Protocol.kt @@ -117,12 +117,7 @@ abstract class Protocol { Log.d(TAG, "addRoute: $inetNetwork") vpnBuilder.addRoute(inetNetwork) } else { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - Log.d(TAG, "excludeRoute: $inetNetwork") - vpnBuilder.excludeRoute(inetNetwork) - } else { - Log.e(TAG, "Trying to exclude route $inetNetwork on old Android") - } + Log.e(TAG, "Trying to exclude route $inetNetwork on old Android") } } @@ -139,13 +134,6 @@ abstract class Protocol { Log.d(TAG, "setMtu: ${config.mtu}") vpnBuilder.setMtu(config.mtu) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - config.httpProxy?.let { - Log.d(TAG, "setHttpProxy: $it") - vpnBuilder.setHttpProxy(it) - } - } - if (config.allowAllAF) { Log.d(TAG, "allowFamily") vpnBuilder.allowFamily(OsConstants.AF_INET) @@ -155,8 +143,6 @@ abstract class Protocol { Log.d(TAG, "setBlocking: ${config.blockingMode}") vpnBuilder.setBlocking(config.blockingMode) vpnBuilder.setUnderlyingNetworks(null) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) - vpnBuilder.setMetered(false) } } diff --git a/client/android/protocolApi/src/main/kotlin/ProtocolConfig.kt b/client/android/protocolApi/src/main/kotlin/ProtocolConfig.kt index bebcea4c..3310c300 100644 --- a/client/android/protocolApi/src/main/kotlin/ProtocolConfig.kt +++ b/client/android/protocolApi/src/main/kotlin/ProtocolConfig.kt @@ -145,7 +145,7 @@ open class ProtocolConfig protected constructor( } // for older versions of Android, build a list of subnets without excluded routes // and add them to routes - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU && routes.any { !it.include }) { + if (routes.any { !it.include }) { val ipRangeSet = IpRangeSet() routes.forEach { if (it.include) ipRangeSet.add(IpRange(it.inetNetwork)) diff --git a/client/android/qt/build.gradle.kts b/client/android/qt/build.gradle.kts index 6b1d3fd1..139adf4f 100644 --- a/client/android/qt/build.gradle.kts +++ b/client/android/qt/build.gradle.kts @@ -21,5 +21,5 @@ android { } dependencies { - api(fileTree(mapOf("dir" to "../libs", "include" to listOf("*.jar")))) + implementation(fileTree(mapOf("dir" to "../libs", "include" to listOf("*.jar")))) } diff --git a/client/android/src/org/amnezia/vpn/AmneziaActivity.kt b/client/android/src/org/amnezia/vpn/AmneziaActivity.kt index d5026425..93bbf37e 100644 --- a/client/android/src/org/amnezia/vpn/AmneziaActivity.kt +++ b/client/android/src/org/amnezia/vpn/AmneziaActivity.kt @@ -3,8 +3,6 @@ package org.amnezia.vpn import android.Manifest import android.annotation.SuppressLint import android.app.AlertDialog -import android.app.NotificationManager -import android.content.BroadcastReceiver import android.content.ComponentName import android.content.Intent import android.content.Intent.EXTRA_MIME_TYPES @@ -68,7 +66,6 @@ class AmneziaActivity : QtActivity() { private var isWaitingStatus = true private var isServiceConnected = false private var isInBoundState = false - private var notificationStateReceiver: BroadcastReceiver? = null private lateinit var vpnServiceMessenger: IpcMessenger private val actionResultHandlers = mutableMapOf() @@ -176,7 +173,6 @@ class AmneziaActivity : QtActivity() { doBindService() } ) - registerBroadcastReceivers() intent?.let(::processIntent) runBlocking { vpnProto = proto.await() } } @@ -192,26 +188,6 @@ class AmneziaActivity : QtActivity() { } } - private fun registerBroadcastReceivers() { - notificationStateReceiver = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - registerBroadcastReceiver( - arrayOf( - NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED, - NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED - ) - ) { - Log.d( - TAG, "Notification state changed: ${it?.action}, blocked = " + - "${it?.getBooleanExtra(NotificationManager.EXTRA_BLOCKED_STATE, false)}" - ) - mainScope.launch { - qtInitialized.await() - QtAndroidController.onNotificationStateChanged() - } - } - } else null - } - override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) Log.d(TAG, "onNewIntent: $intent") @@ -257,8 +233,6 @@ class AmneziaActivity : QtActivity() { override fun onDestroy() { Log.d(TAG, "Destroy Amnezia activity") - unregisterBroadcastReceiver(notificationStateReceiver) - notificationStateReceiver = null mainScope.cancel() super.onDestroy() } @@ -664,7 +638,7 @@ class AmneziaActivity : QtActivity() { } @Suppress("unused") - fun isNotificationPermissionGranted(): Boolean = applicationContext.isNotificationPermissionGranted() + fun isNotificationPermissionGranted(): Boolean = true @Suppress("unused") fun requestNotificationPermission() { diff --git a/client/android/src/org/amnezia/vpn/AmneziaTileService.kt b/client/android/src/org/amnezia/vpn/AmneziaTileService.kt index 32d5710d..117755e2 100644 --- a/client/android/src/org/amnezia/vpn/AmneziaTileService.kt +++ b/client/android/src/org/amnezia/vpn/AmneziaTileService.kt @@ -1,12 +1,9 @@ package org.amnezia.vpn -import android.annotation.SuppressLint -import android.app.PendingIntent import android.content.ComponentName import android.content.Intent import android.content.ServiceConnection import android.net.VpnService -import android.os.Build import android.os.IBinder import android.os.Messenger import android.service.quicksettings.Tile @@ -148,7 +145,8 @@ class AmneziaTileService : TileService() { Intent(this, AmneziaActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }.also { - startActivityAndCollapseCompat(it) + @Suppress("DEPRECATION") + startActivityAndCollapse(it) } } } @@ -192,7 +190,8 @@ class AmneziaTileService : TileService() { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) putExtra(EXTRA_PROTOCOL, vpnProto) }.also { - startActivityAndCollapseCompat(it) + @Suppress("DEPRECATION") + startActivityAndCollapse(it) } false } else { @@ -216,23 +215,6 @@ class AmneziaTileService : TileService() { private fun stopVpn() = vpnServiceMessenger.send(Action.DISCONNECT) - @SuppressLint("StartActivityAndCollapseDeprecated") - private fun startActivityAndCollapseCompat(intent: Intent) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { - startActivityAndCollapse( - PendingIntent.getActivity( - applicationContext, - 0, - intent, - PendingIntent.FLAG_IMMUTABLE - ) - ) - } else { - @Suppress("DEPRECATION") - startActivityAndCollapse(intent) - } - } - private fun updateVpnState(state: ProtocolState) = scope.launch { VpnStateStore.store { it.copy(protocolState = state) } } @@ -249,17 +231,14 @@ class AmneziaTileService : TileService() { when (val protocolState = vpnState.protocolState) { CONNECTED -> { state = Tile.STATE_ACTIVE - subtitleCompat = null } DISCONNECTED, UNKNOWN -> { state = Tile.STATE_INACTIVE - subtitleCompat = null } CONNECTING, DISCONNECTING, RECONNECTING -> { state = Tile.STATE_UNAVAILABLE - subtitleCompat = getString(protocolState) } } updateTile() @@ -267,17 +246,4 @@ class AmneziaTileService : TileService() { // double update to fix weird visual glitches tile.updateTile() } - - private var Tile.subtitleCompat: CharSequence? - set(value) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - this.subtitle = value - } - } - get() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - return this.subtitle - } - return null - } } diff --git a/client/android/src/org/amnezia/vpn/AmneziaVpnService.kt b/client/android/src/org/amnezia/vpn/AmneziaVpnService.kt index 937127ee..4ce51130 100644 --- a/client/android/src/org/amnezia/vpn/AmneziaVpnService.kt +++ b/client/android/src/org/amnezia/vpn/AmneziaVpnService.kt @@ -3,14 +3,10 @@ package org.amnezia.vpn import android.annotation.SuppressLint import android.app.ActivityManager import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE -import android.app.NotificationManager import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST -import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED import android.net.VpnService -import android.os.Build import android.os.Handler import android.os.IBinder import android.os.Looper @@ -104,7 +100,6 @@ open class AmneziaVpnService : VpnService() { private lateinit var networkState: NetworkState private lateinit var trafficStats: TrafficStats private var controlReceiver: BroadcastReceiver? = null - private var notificationStateReceiver: BroadcastReceiver? = null private var screenOnReceiver: BroadcastReceiver? = null private var screenOffReceiver: BroadcastReceiver? = null private val clientMessengers = ConcurrentHashMap() @@ -189,16 +184,6 @@ open class AmneziaVpnService : VpnService() { Messenger(actionMessageHandler) } - /** - * Notification setup - */ - private val foregroundServiceTypeCompat - get() = when { - Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE -> FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED - Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> FOREGROUND_SERVICE_TYPE_MANIFEST - else -> 0 - } - private val serviceNotification: ServiceNotification by lazy(NONE) { ServiceNotification(this) } /** @@ -232,7 +217,7 @@ open class AmneziaVpnService : VpnService() { ServiceCompat.startForeground( this, NOTIFICATION_ID, serviceNotification.buildNotification(serverName, vpnProto?.label, protocolState.value), - foregroundServiceTypeCompat + 0 ) return START_REDELIVER_INTENT } @@ -309,23 +294,6 @@ open class AmneziaVpnService : VpnService() { } } - notificationStateReceiver = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - registerBroadcastReceiver( - arrayOf( - NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED, - NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED - ) - ) { - val state = it?.getBooleanExtra(NotificationManager.EXTRA_BLOCKED_STATE, false) - Log.d(TAG, "Notification state changed: ${it?.action}, blocked = $state") - if (state == false) { - enableNotification() - } else { - disableNotification() - } - } - } else null - registerScreenStateBroadcastReceivers() } @@ -353,10 +321,8 @@ open class AmneziaVpnService : VpnService() { private fun unregisterBroadcastReceivers() { Log.d(TAG, "Unregister broadcast receivers") unregisterBroadcastReceiver(controlReceiver) - unregisterBroadcastReceiver(notificationStateReceiver) unregisterScreenStateBroadcastReceivers() controlReceiver = null - notificationStateReceiver = null } /** diff --git a/client/android/src/org/amnezia/vpn/ServiceNotification.kt b/client/android/src/org/amnezia/vpn/ServiceNotification.kt index f4707731..a991eafc 100644 --- a/client/android/src/org/amnezia/vpn/ServiceNotification.kt +++ b/client/android/src/org/amnezia/vpn/ServiceNotification.kt @@ -1,19 +1,15 @@ package org.amnezia.vpn -import android.Manifest.permission import android.annotation.SuppressLint import android.app.Notification -import android.app.NotificationManager import android.app.PendingIntent import android.content.Context import android.content.Intent -import android.content.pm.PackageManager import android.os.Build import androidx.core.app.NotificationChannelCompat.Builder import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat.Action import androidx.core.app.NotificationManagerCompat -import androidx.core.content.ContextCompat import org.amnezia.vpn.protocol.ProtocolState import org.amnezia.vpn.protocol.ProtocolState.CONNECTED import org.amnezia.vpn.protocol.ProtocolState.DISCONNECTED @@ -85,29 +81,17 @@ class ServiceNotification(private val context: Context) { .setSubText(getSpeedString(speed)) .build() - fun isNotificationEnabled(): Boolean { - if (!context.isNotificationPermissionGranted()) return false - if (!notificationManager.areNotificationsEnabled()) return false - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - return notificationManager.getNotificationChannel(NOTIFICATION_CHANNEL_ID) - ?.let { it.importance != NotificationManager.IMPORTANCE_NONE } ?: true - } - return true - } + fun isNotificationEnabled(): Boolean = notificationManager.areNotificationsEnabled() @SuppressLint("MissingPermission") fun updateNotification(serverName: String?, protocol: String?, state: ProtocolState) { - if (context.isNotificationPermissionGranted()) { - Log.d(TAG, "Update notification: $serverName, $state") - notificationManager.notify(NOTIFICATION_ID, buildNotification(serverName, protocol, state)) - } + Log.d(TAG, "Update notification: $serverName, $state") + notificationManager.notify(NOTIFICATION_ID, buildNotification(serverName, protocol, state)) } @SuppressLint("MissingPermission") fun updateSpeed(speed: TrafficData) { - if (context.isNotificationPermissionGranted()) { - notificationManager.notify(NOTIFICATION_ID, buildNotification(speed)) - } + notificationManager.notify(NOTIFICATION_ID, buildNotification(speed)) } private fun getSpeedString(traffic: TrafficData) = @@ -168,8 +152,3 @@ class ServiceNotification(private val context: Context) { } } } - -fun Context.isNotificationPermissionGranted(): Boolean = - Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU || - ContextCompat.checkSelfPermission(this, permission.POST_NOTIFICATIONS) == - PackageManager.PERMISSION_GRANTED diff --git a/client/android/src/org/amnezia/vpn/VpnRequestActivity.kt b/client/android/src/org/amnezia/vpn/VpnRequestActivity.kt index c24f5a19..56bcbdea 100644 --- a/client/android/src/org/amnezia/vpn/VpnRequestActivity.kt +++ b/client/android/src/org/amnezia/vpn/VpnRequestActivity.kt @@ -7,7 +7,6 @@ import android.content.Intent import android.content.res.Configuration.UI_MODE_NIGHT_MASK import android.content.res.Configuration.UI_MODE_NIGHT_YES import android.net.VpnService -import android.os.Build import android.os.Bundle import android.provider.Settings import android.widget.Toast @@ -31,12 +30,9 @@ class VpnRequestActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Log.d(TAG, "Start request activity") - vpnProto = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - intent.extras?.getSerializable(EXTRA_PROTOCOL, VpnProto::class.java) - } else { - @Suppress("DEPRECATION") - intent.extras?.getSerializable(EXTRA_PROTOCOL) as VpnProto - } + @Suppress("DEPRECATION") + vpnProto = intent.extras?.getSerializable(EXTRA_PROTOCOL) as VpnProto + val requestIntent = VpnService.prepare(applicationContext) if (requestIntent != null) { if (getSystemService()!!.isKeyguardLocked) { diff --git a/client/android/utils/src/main/kotlin/Log.kt b/client/android/utils/src/main/kotlin/Log.kt index a656b9ea..42832b0d 100644 --- a/client/android/utils/src/main/kotlin/Log.kt +++ b/client/android/utils/src/main/kotlin/Log.kt @@ -10,8 +10,6 @@ import java.io.IOException import java.io.RandomAccessFile import java.nio.channels.FileChannel import java.nio.channels.FileLock -import java.time.LocalDateTime -import java.time.format.DateTimeFormatter import java.util.Date import java.util.Locale import java.util.concurrent.locks.ReentrantLock @@ -41,11 +39,9 @@ private const val LOG_MAX_FILE_SIZE = 1024 * 1024 * | | | create a report and/or terminate the process | */ object Log { - private val dateTimeFormat: Any = - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) DateTimeFormatter.ofPattern(DATE_TIME_PATTERN) - else object : ThreadLocal() { - override fun initialValue(): DateFormat = SimpleDateFormat(DATE_TIME_PATTERN, Locale.US) - } + private val dateTimeFormat = object : ThreadLocal() { + override fun initialValue(): DateFormat = SimpleDateFormat(DATE_TIME_PATTERN, Locale.US) + } private lateinit var logDir: File private val logFile: File by lazy { File(logDir, LOG_FILE_NAME) } @@ -143,12 +139,7 @@ object Log { } private fun formatLogMsg(tag: String, msg: String, priority: Priority): String { - val date = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - LocalDateTime.now().format(dateTimeFormat as DateTimeFormatter) - } else { - @Suppress("UNCHECKED_CAST") - (dateTimeFormat as ThreadLocal).get()?.format(Date()) - } + val date = dateTimeFormat.get()?.format(Date()) return "$date ${Process.myPid()} ${Process.myTid()} $priority [${Thread.currentThread().name}] " + "$tag: $msg\n" } diff --git a/client/android/utils/src/main/kotlin/net/NetworkState.kt b/client/android/utils/src/main/kotlin/net/NetworkState.kt index b71bf393..90988f38 100644 --- a/client/android/utils/src/main/kotlin/net/NetworkState.kt +++ b/client/android/utils/src/main/kotlin/net/NetworkState.kt @@ -8,11 +8,9 @@ import android.net.NetworkCapabilities import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED import android.net.NetworkRequest -import android.os.Build import android.os.Handler import androidx.core.content.getSystemService import kotlin.LazyThreadSafetyMode.NONE -import kotlinx.coroutines.delay import org.amnezia.vpn.util.Log private const val TAG = "NetworkState" @@ -47,12 +45,8 @@ class NetworkState( override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) { Log.d(TAG, "onCapabilitiesChanged: $network, $networkCapabilities") - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + handler.post { checkNetworkState(network, networkCapabilities) - } else { - handler.post { - checkNetworkState(network, networkCapabilities) - } } } @@ -82,35 +76,10 @@ class NetworkState( } } - suspend fun bindNetworkListener() { + fun bindNetworkListener() { if (isListenerBound) return Log.d(TAG, "Bind network listener") - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - connectivityManager.registerBestMatchingNetworkCallback(networkRequest, networkCallback, handler) - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val numberAttempts = 300 - var attemptCount = 0 - while(true) { - try { - connectivityManager.requestNetwork(networkRequest, networkCallback, handler) - break - } catch (e: SecurityException) { - Log.e(TAG, "Failed to bind network listener: $e") - // Android 11 bug: https://issuetracker.google.com/issues/175055271 - if (e.message?.startsWith("Package android does not belong to") == true) { - if (++attemptCount > numberAttempts) { - throw e - } - delay(1000) - continue - } else { - throw e - } - } - } - } else { - connectivityManager.requestNetwork(networkRequest, networkCallback) - } + connectivityManager.requestNetwork(networkRequest, networkCallback) isListenerBound = true } diff --git a/client/android/utils/src/main/kotlin/net/TrafficStats.kt b/client/android/utils/src/main/kotlin/net/TrafficStats.kt index 170d164e..f5a44bec 100644 --- a/client/android/utils/src/main/kotlin/net/TrafficStats.kt +++ b/client/android/utils/src/main/kotlin/net/TrafficStats.kt @@ -1,7 +1,6 @@ package org.amnezia.vpn.util.net import android.net.TrafficStats -import android.os.Build import android.os.Process import android.os.SystemClock import kotlin.math.roundToLong @@ -17,18 +16,12 @@ class TrafficStats { private var lastTrafficData = TrafficData.ZERO private var lastTimestamp = 0L - private val getTrafficDataCompat: () -> TrafficData = - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - val iface = "tun0" - fun(): TrafficData { - return TrafficData(TrafficStats.getRxBytes(iface), TrafficStats.getTxBytes(iface)) - } - } else { - val uid = Process.myUid() - fun(): TrafficData { - return TrafficData(TrafficStats.getUidRxBytes(uid), TrafficStats.getUidTxBytes(uid)) - } + private val getTrafficDataCompat: () -> TrafficData = run { + val uid = Process.myUid() + fun(): TrafficData { + return TrafficData(TrafficStats.getUidRxBytes(uid), TrafficStats.getUidTxBytes(uid)) } + } fun reset() { lastTrafficData = getTrafficDataCompat() From ce9a062bea2890d3fb87134d5e6baef0b8d6f830 Mon Sep 17 00:00:00 2001 From: albexk Date: Wed, 2 Oct 2024 15:20:55 +0300 Subject: [PATCH 4/9] Update version code to separate versions for new and old Androids --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b8989a6..3fb66178 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d") set(RELEASE_DATE "${CURRENT_DATE}") set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH}) -set(APP_ANDROID_VERSION_CODE 66) +set(APP_ANDROID_VERSION_CODE 1066) if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") set(MZ_PLATFORM_NAME "linux") From 4d6174f5d81ca0db1485f25d5354d8b8560bc100 Mon Sep 17 00:00:00 2001 From: albexk Date: Wed, 2 Oct 2024 15:25:25 +0300 Subject: [PATCH 5/9] Fix GA --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index f3ac2ff1..dbd52e0f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -313,7 +313,7 @@ jobs: version: ${{ env.QT_VERSION }} host: 'linux' target: 'desktop' - arch: 'linux_gcc_64' + arch: 'gcc_64' modules: ${{ env.QT_MODULES }} dir: ${{ runner.temp }} extra: '--external 7z --base ${{ env.QT_MIRROR }}' From 1ae9a57b570e26cd108c90ec7d2b32924db6615a Mon Sep 17 00:00:00 2001 From: albexk Date: Tue, 22 Oct 2024 14:19:44 +0300 Subject: [PATCH 6/9] Fix merge --- client/android/gradle.properties | 2 +- .../src/org/amnezia/vpn/AmneziaActivity.kt | 61 ------------------- client/cmake/android.cmake | 2 +- 3 files changed, 2 insertions(+), 63 deletions(-) diff --git a/client/android/gradle.properties b/client/android/gradle.properties index ce651e1c..5a27838c 100644 --- a/client/android/gradle.properties +++ b/client/android/gradle.properties @@ -33,7 +33,7 @@ android.library.defaults.buildfeatures.androidresources=false # For development copy and set local values for these parameters in local.properties #androidCompileSdkVersion=android-34 #androidBuildToolsVersion=34.0.0 -#qtMinSdkVersion=26 +#qtMinSdkVersion=24 #qtTargetSdkVersion=34 #androidNdkVersion=26.1.10909125 #qtTargetAbiList=x86_64 diff --git a/client/android/src/org/amnezia/vpn/AmneziaActivity.kt b/client/android/src/org/amnezia/vpn/AmneziaActivity.kt index 68a5c37b..30bf09a3 100644 --- a/client/android/src/org/amnezia/vpn/AmneziaActivity.kt +++ b/client/android/src/org/amnezia/vpn/AmneziaActivity.kt @@ -19,7 +19,6 @@ import android.os.Looper import android.os.Message import android.os.Messenger import android.provider.Settings -import android.view.MotionEvent import android.view.WindowManager.LayoutParams import android.webkit.MimeTypeMap import android.widget.Toast @@ -695,66 +694,6 @@ class AmneziaActivity : QtActivity() { } } - // workaround for a bug in Qt that causes the mouse click event not to be handled - // also disable right-click, as it causes the application to crash - private var lastButtonState = 0 - private fun MotionEvent.fixCopy(): MotionEvent = MotionEvent.obtain( - downTime, - eventTime, - action, - pointerCount, - (0 until pointerCount).map { i -> - MotionEvent.PointerProperties().apply { - getPointerProperties(i, this) - } - }.toTypedArray(), - (0 until pointerCount).map { i -> - MotionEvent.PointerCoords().apply { - getPointerCoords(i, this) - } - }.toTypedArray(), - metaState, - MotionEvent.BUTTON_PRIMARY, - xPrecision, - yPrecision, - deviceId, - edgeFlags, - source, - flags - ) - - private fun handleMouseEvent(ev: MotionEvent, superDispatch: (MotionEvent?) -> Boolean): Boolean { - when (ev.action) { - MotionEvent.ACTION_DOWN -> { - lastButtonState = ev.buttonState - if (ev.buttonState == MotionEvent.BUTTON_SECONDARY) return true - } - - MotionEvent.ACTION_UP -> { - when (lastButtonState) { - MotionEvent.BUTTON_SECONDARY -> return true - MotionEvent.BUTTON_PRIMARY -> { - val modEvent = ev.fixCopy() - return superDispatch(modEvent).apply { modEvent.recycle() } - } - } - } - } - return superDispatch(ev) - } - - override fun dispatchTouchEvent(ev: MotionEvent?): Boolean { - if (ev != null && ev.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE) { - return handleMouseEvent(ev) { super.dispatchTouchEvent(it) } - } - return super.dispatchTouchEvent(ev) - } - - override fun dispatchTrackballEvent(ev: MotionEvent?): Boolean { - ev?.let { return handleMouseEvent(ev) { super.dispatchTrackballEvent(it) }} - return super.dispatchTrackballEvent(ev) - } - /** * Utils methods */ diff --git a/client/cmake/android.cmake b/client/cmake/android.cmake index 34ca5bff..c96d9ab8 100644 --- a/client/cmake/android.cmake +++ b/client/cmake/android.cmake @@ -1,6 +1,6 @@ message("Client android ${CMAKE_ANDROID_ARCH_ABI} build") -set(APP_ANDROID_MIN_SDK 26) +set(APP_ANDROID_MIN_SDK 24) set(ANDROID_PLATFORM "android-${APP_ANDROID_MIN_SDK}" CACHE STRING "The minimum API level supported by the application or library" FORCE) From 5445e6637b6f126db78c3666828e2f9ed0c5e964 Mon Sep 17 00:00:00 2001 From: Nethius Date: Tue, 8 Jul 2025 14:25:03 +0800 Subject: [PATCH 7/9] chore: minor fixes (#1616) * chore: removed unnecessary qdebug * fix: return soft and hide strict killswitch --- .../ui/controllers/api/apiConfigsController.cpp | 2 -- client/ui/qml/Pages2/PageSettingsKillSwitch.qml | 15 ++++++++------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/client/ui/controllers/api/apiConfigsController.cpp b/client/ui/controllers/api/apiConfigsController.cpp index 0b0a9b92..0f42beb7 100644 --- a/client/ui/controllers/api/apiConfigsController.cpp +++ b/client/ui/controllers/api/apiConfigsController.cpp @@ -221,8 +221,6 @@ namespace serverConfig[configKey::apiConfig] = apiConfig; - qDebug() << serverConfig; - return ErrorCode::NoError; } } diff --git a/client/ui/qml/Pages2/PageSettingsKillSwitch.qml b/client/ui/qml/Pages2/PageSettingsKillSwitch.qml index ca1cd0d4..d6d73b20 100644 --- a/client/ui/qml/Pages2/PageSettingsKillSwitch.qml +++ b/client/ui/qml/Pages2/PageSettingsKillSwitch.qml @@ -62,8 +62,7 @@ PageType { Layout.leftMargin: 16 Layout.rightMargin: 16 - visible: false - // enabled: SettingsController.isKillSwitchEnabled && !ConnectionController.isConnected + enabled: SettingsController.isKillSwitchEnabled && !ConnectionController.isConnected checked: !SettingsController.strictKillSwitchEnabled text: qsTr("Soft KillSwitch") @@ -74,9 +73,7 @@ PageType { } } - DividerType { - visible: false - } + DividerType {} VerticalRadioButton { id: strictKillSwitch @@ -84,7 +81,9 @@ PageType { Layout.leftMargin: 16 Layout.rightMargin: 16 - enabled: SettingsController.isKillSwitchEnabled && !ConnectionController.isConnected + visible: false + enabled: false + // enabled: SettingsController.isKillSwitchEnabled && !ConnectionController.isConnected checked: SettingsController.strictKillSwitchEnabled text: qsTr("Strict KillSwitch") @@ -106,7 +105,9 @@ PageType { } } - DividerType {} + DividerType { + visible: false + } LabelWithButtonType { Layout.topMargin: 32 From 10a107716cf3a566f77e99a56066140e61bdae0b Mon Sep 17 00:00:00 2001 From: Nethius Date: Tue, 8 Jul 2025 15:06:52 +0800 Subject: [PATCH 8/9] fix: fixed awg 1.5 fields processing for ios (#1700) --- client/platforms/ios/WGConfig.swift | 76 ++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 23 deletions(-) diff --git a/client/platforms/ios/WGConfig.swift b/client/platforms/ios/WGConfig.swift index 8f693387..537687f1 100644 --- a/client/platforms/ios/WGConfig.swift +++ b/client/platforms/ios/WGConfig.swift @@ -46,29 +46,59 @@ struct WGConfig: Decodable { } var settings: String { - junkPacketCount == nil ? "" : - """ - Jc = \(junkPacketCount!) - Jmin = \(junkPacketMinSize!) - Jmax = \(junkPacketMaxSize!) - S1 = \(initPacketJunkSize!) - S2 = \(responsePacketJunkSize!) - S3 = \(cookieReplyPacketJunkSize!) - S4 = \(transportPacketJunkSize!) - H1 = \(initPacketMagicHeader!) - H2 = \(responsePacketMagicHeader!) - H3 = \(underloadPacketMagicHeader!) - H4 = \(transportPacketMagicHeader!) - I1 = \(specialJunk1!) - I2 = \(specialJunk2!) - I3 = \(specialJunk3!) - I4 = \(specialJunk4!) - I5 = \(specialJunk5!) - J1 = \(controlledJunk1!) - J2 = \(controlledJunk2!) - J3 = \(controlledJunk3!) - Itime = \(specialHandshakeTimeout!) - """ + guard junkPacketCount != nil else { return "" } + + var settingsLines: [String] = [] + + // Required parameters when junkPacketCount is present + settingsLines.append("Jc = \(junkPacketCount!)") + settingsLines.append("Jmin = \(junkPacketMinSize!)") + settingsLines.append("Jmax = \(junkPacketMaxSize!)") + settingsLines.append("S1 = \(initPacketJunkSize!)") + settingsLines.append("S2 = \(responsePacketJunkSize!)") + + settingsLines.append("H1 = \(initPacketMagicHeader!)") + settingsLines.append("H2 = \(responsePacketMagicHeader!)") + settingsLines.append("H3 = \(underloadPacketMagicHeader!)") + settingsLines.append("H4 = \(transportPacketMagicHeader!)") + + // Optional parameters - only add if not nil and not empty + if let s3 = cookieReplyPacketJunkSize, !s3.isEmpty { + settingsLines.append("S3 = \(s3)") + } + if let s4 = transportPacketJunkSize, !s4.isEmpty { + settingsLines.append("S4 = \(s4)") + } + + if let i1 = specialJunk1, !i1.isEmpty { + settingsLines.append("I1 = \(i1)") + } + if let i2 = specialJunk2, !i2.isEmpty { + settingsLines.append("I2 = \(i2)") + } + if let i3 = specialJunk3, !i3.isEmpty { + settingsLines.append("I3 = \(i3)") + } + if let i4 = specialJunk4, !i4.isEmpty { + settingsLines.append("I4 = \(i4)") + } + if let i5 = specialJunk5, !i5.isEmpty { + settingsLines.append("I5 = \(i5)") + } + if let j1 = controlledJunk1, !j1.isEmpty { + settingsLines.append("J1 = \(j1)") + } + if let j2 = controlledJunk2, !j2.isEmpty { + settingsLines.append("J2 = \(j2)") + } + if let j3 = controlledJunk3, !j3.isEmpty { + settingsLines.append("J3 = \(j3)") + } + if let itime = specialHandshakeTimeout, !itime.isEmpty { + settingsLines.append("Itime = \(itime)") + } + + return settingsLines.joined(separator: "\n") } var str: String {