1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
/*
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
package com.wireguard.android.preference
import android.content.Context
import android.content.Intent
import android.util.AttributeSet
import android.util.Log
import androidx.lifecycle.lifecycleScope
import androidx.preference.Preference
import com.wireguard.android.Application
import com.wireguard.android.R
import com.wireguard.android.activity.SettingsActivity
import com.wireguard.android.backend.Tunnel
import com.wireguard.android.backend.WgQuickBackend
import com.wireguard.android.util.UserKnobs
import com.wireguard.android.util.activity
import com.wireguard.android.util.lifecycleScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlin.system.exitProcess
class KernelModuleEnablerPreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) {
private var state = State.UNKNOWN
init {
isVisible = false
lifecycleScope.launch {
setState(if (Application.getBackend() is WgQuickBackend) State.ENABLED else State.DISABLED)
}
}
override fun getSummary() = if (state == State.UNKNOWN) "" else context.getString(state.summaryResourceId)
override fun getTitle() = if (state == State.UNKNOWN) "" else context.getString(state.titleResourceId)
override fun onClick() {
activity.lifecycleScope.launch {
if (state == State.DISABLED) {
setState(State.ENABLING)
UserKnobs.setEnableKernelModule(true)
} else if (state == State.ENABLED) {
setState(State.DISABLING)
UserKnobs.setEnableKernelModule(false)
}
val observableTunnels = Application.getTunnelManager().getTunnels()
val downings = observableTunnels.map { async(SupervisorJob()) { it.setStateAsync(Tunnel.State.DOWN) } }
try {
downings.awaitAll()
withContext(Dispatchers.IO) {
val restartIntent = Intent(context, SettingsActivity::class.java)
restartIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
restartIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
Application.get().startActivity(restartIntent)
exitProcess(0)
}
} catch (e: Throwable) {
Log.e(TAG, Log.getStackTraceString(e))
}
}
}
private fun setState(state: State) {
if (this.state == state) return
this.state = state
if (isEnabled != state.shouldEnableView) isEnabled = state.shouldEnableView
if (isVisible != state.visible) isVisible = state.visible
notifyChanged()
}
private enum class State(val titleResourceId: Int, val summaryResourceId: Int, val shouldEnableView: Boolean, val visible: Boolean) {
UNKNOWN(0, 0, false, false),
ENABLED(R.string.module_enabler_enabled_title, R.string.module_enabler_enabled_summary, true, true),
DISABLED(R.string.module_enabler_disabled_title, R.string.module_enabler_disabled_summary, true, true),
ENABLING(R.string.module_enabler_disabled_title, R.string.success_application_will_restart, false, true),
DISABLING(R.string.module_enabler_enabled_title, R.string.success_application_will_restart, false, true);
}
companion object {
private const val TAG = "WireGuard/KernelModuleEnablerPreference"
}
}
|