summaryrefslogtreecommitdiffhomepage
path: root/android/src
diff options
context:
space:
mode:
Diffstat (limited to 'android/src')
-rw-r--r--android/src/main/AndroidManifest.xml4
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/MainActivity.kt48
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadVpnService.kt72
3 files changed, 75 insertions, 49 deletions
diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
index d025f278a5..88dfa8ae67 100644
--- a/android/src/main/AndroidManifest.xml
+++ b/android/src/main/AndroidManifest.xml
@@ -15,6 +15,8 @@
<activity
android:name=".MainActivity"
android:label="@string/app_name"
+ android:configChanges="orientation"
+ android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan"
>
<intent-filter>
@@ -24,7 +26,7 @@
</activity>
<service
- android:name=".MullvadVpnService$InnerVpnService"
+ android:name=".MullvadVpnService"
android:permission="android.permission.BIND_VPN_SERVICE"
>
<intent-filter>
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/MainActivity.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/MainActivity.kt
index 320b2e1c94..927a6ba05e 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/MainActivity.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/MainActivity.kt
@@ -9,7 +9,11 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
+import android.content.ComponentName
+import android.content.Intent
+import android.content.ServiceConnection
import android.os.Bundle
+import android.os.IBinder
import android.support.v4.app.FragmentActivity
import net.mullvad.mullvadvpn.model.RelaySettings
@@ -18,9 +22,7 @@ import net.mullvad.mullvadvpn.relaylist.RelayItem
import net.mullvad.mullvadvpn.relaylist.RelayList
class MainActivity : FragmentActivity() {
- val activityCreated = CompletableDeferred<Unit>()
-
- val asyncDaemon = startDaemon()
+ var asyncDaemon = CompletableDeferred<MullvadDaemon>()
val daemon
get() = runBlocking { asyncDaemon.await() }
@@ -37,20 +39,50 @@ class MainActivity : FragmentActivity() {
var selectedRelayItem: RelayItem? = null
private val restoreSelectedRelayListItemJob = restoreSelectedRelayListItem()
+ private var waitForDaemonJob: Job? = null
+
+ private val serviceConnection = object : ServiceConnection {
+ override fun onServiceConnected(className: ComponentName, binder: IBinder) {
+ val localBinder = binder as MullvadVpnService.LocalBinder
+
+ waitForDaemonJob = GlobalScope.launch(Dispatchers.Default) {
+ asyncDaemon.complete(localBinder.asyncDaemon.await())
+ }
+ }
+
+ override fun onServiceDisconnected(className: ComponentName) {
+ asyncDaemon.cancel()
+ asyncDaemon = CompletableDeferred<MullvadDaemon>()
+ }
+ }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main)
- activityCreated.complete(Unit)
-
if (savedInstanceState == null) {
addInitialFragment()
}
}
+ override fun onStart() {
+ super.onStart()
+
+ val intent = Intent(this, MullvadVpnService::class.java)
+
+ startService(intent)
+ bindService(intent, serviceConnection, 0)
+ }
+
+ override fun onStop() {
+ unbindService(serviceConnection)
+
+ super.onStop()
+ }
+
override fun onDestroy() {
restoreSelectedRelayListItemJob.cancel()
+ waitForDaemonJob?.cancel()
asyncSettings.cancel()
asyncRelayList.cancel()
asyncDaemon.cancel()
@@ -65,12 +97,6 @@ class MainActivity : FragmentActivity() {
}
}
- private fun startDaemon() = GlobalScope.async(Dispatchers.Default) {
- activityCreated.await()
- ApiRootCaFile().extract(this@MainActivity)
- MullvadDaemon(MullvadVpnService(this@MainActivity))
- }
-
private fun fetchRelayList() = GlobalScope.async(Dispatchers.Default) {
RelayList(asyncDaemon.await().getRelayLocations())
}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadVpnService.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadVpnService.kt
index ec71738ef2..8785c94230 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadVpnService.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadVpnService.kt
@@ -2,61 +2,44 @@ package net.mullvad.mullvadvpn
import java.net.InetAddress
+import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.VpnService
+import android.os.Binder
+import android.os.IBinder
import net.mullvad.mullvadvpn.model.TunConfig
-var INNER_VPN_SERVICE = CompletableDeferred<MullvadVpnService.InnerVpnService>()
-var SERVICE_NOT_RUNNING = true
+class MullvadVpnService : VpnService() {
+ private val created = CompletableDeferred<Unit>()
+ private val binder = LocalBinder()
-class MullvadVpnService(val context: Context) {
- class InnerVpnService : VpnService() {
- override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
- INNER_VPN_SERVICE.complete(this)
+ val asyncDaemon = startDaemon()
+ val daemon
+ get() = runBlocking { asyncDaemon.await() }
- return super.onStartCommand(intent, flags, startId)
- }
-
- override fun onDestroy() {
- INNER_VPN_SERVICE = CompletableDeferred<MullvadVpnService.InnerVpnService>()
- SERVICE_NOT_RUNNING = true
- super.onDestroy()
- }
-
- fun builder(): Builder {
- return Builder()
- }
+ override fun onCreate() {
+ created.complete(Unit)
}
- fun createTun(config: TunConfig): Int {
- return createTun(config, startService())
+ override fun onBind(intent: Intent): IBinder {
+ return super.onBind(intent) ?: binder
}
- fun bypass(socket: Int): Boolean {
- return startService().protect(socket)
+ override fun onDestroy() {
+ asyncDaemon.cancel()
+ created.cancel()
}
- private fun startService(): InnerVpnService {
- lateinit var service: InnerVpnService
-
- if (SERVICE_NOT_RUNNING) {
- SERVICE_NOT_RUNNING = false
- context.startService(Intent(context, InnerVpnService::class.java))
- }
-
- runBlocking { service = INNER_VPN_SERVICE.await() }
-
- return service
- }
-
- private fun createTun(config: TunConfig, service: InnerVpnService): Int {
- val builder = service.builder().apply {
+ fun createTun(config: TunConfig): Int {
+ val builder = Builder().apply {
for (address in config.addresses) {
addAddress(address, 32)
}
@@ -76,4 +59,19 @@ class MullvadVpnService(val context: Context) {
return vpnInterface.detachFd()
}
+
+ fun bypass(socket: Int): Boolean {
+ return protect(socket)
+ }
+
+ inner class LocalBinder : Binder() {
+ val asyncDaemon
+ get() = this@MullvadVpnService.asyncDaemon
+ }
+
+ private fun startDaemon() = GlobalScope.async(Dispatchers.Default) {
+ created.await()
+ ApiRootCaFile().extract(application)
+ MullvadDaemon(this@MullvadVpnService)
+ }
}