coroutines: convert low-hanging fruits

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2020-09-14 14:27:55 +02:00
parent dd0ff8fe60
commit 2fc0bb1a03
5 changed files with 106 additions and 73 deletions

View File

@ -19,6 +19,10 @@ import com.wireguard.android.R
import com.wireguard.android.backend.WgQuickBackend import com.wireguard.android.backend.WgQuickBackend
import com.wireguard.android.util.AdminKnobs import com.wireguard.android.util.AdminKnobs
import com.wireguard.android.util.ModuleLoader import com.wireguard.android.util.ModuleLoader
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.ArrayList import java.util.ArrayList
import java.util.Arrays import java.util.Arrays
@ -117,13 +121,15 @@ class SettingsActivity : ThemeChangeAwareActivity() {
moduleInstaller?.parent?.removePreference(moduleInstaller) moduleInstaller?.parent?.removePreference(moduleInstaller)
} else { } else {
kernelModuleDisabler?.parent?.removePreference(kernelModuleDisabler) kernelModuleDisabler?.parent?.removePreference(kernelModuleDisabler)
Application.getAsyncWorker().runAsync(Application.getRootShell()::start).whenComplete { _, e -> CoroutineScope(Dispatchers.Main).launch {
if (e == null) try {
withContext(Dispatchers.IO) { Application.getRootShell().start() }
moduleInstaller?.isVisible = true moduleInstaller?.isVisible = true
else } catch (_: Exception) {
moduleInstaller?.parent?.removePreference(moduleInstaller) moduleInstaller?.parent?.removePreference(moduleInstaller)
} }
} }
} }
} }
} }
}

View File

@ -22,6 +22,10 @@ import com.wireguard.android.databinding.ObservableKeyedArrayList
import com.wireguard.android.model.ApplicationData import com.wireguard.android.model.ApplicationData
import com.wireguard.android.util.ErrorMessages import com.wireguard.android.util.ErrorMessages
import com.wireguard.android.util.requireTargetFragment import com.wireguard.android.util.requireTargetFragment
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class AppListDialogFragment : DialogFragment() { class AppListDialogFragment : DialogFragment() {
private val appData = ObservableKeyedArrayList<String, ApplicationData>() private val appData = ObservableKeyedArrayList<String, ApplicationData>()
@ -33,11 +37,13 @@ class AppListDialogFragment : DialogFragment() {
private fun loadData() { private fun loadData() {
val activity = activity ?: return val activity = activity ?: return
val pm = activity.packageManager val pm = activity.packageManager
Application.getAsyncWorker().supplyAsync<List<ApplicationData>> { CoroutineScope(Dispatchers.Default).launch {
try {
val applicationData: MutableList<ApplicationData> = ArrayList()
withContext(Dispatchers.IO) {
val launcherIntent = Intent(Intent.ACTION_MAIN, null) val launcherIntent = Intent(Intent.ACTION_MAIN, null)
launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER) launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER)
val resolveInfos = pm.queryIntentActivities(launcherIntent, 0) val resolveInfos = pm.queryIntentActivities(launcherIntent, 0)
val applicationData: MutableList<ApplicationData> = ArrayList()
resolveInfos.forEach { resolveInfos.forEach {
val packageName = it.activityInfo.packageName val packageName = it.activityInfo.packageName
val appData = ApplicationData(it.loadIcon(pm), it.loadLabel(pm).toString(), packageName, currentlySelectedApps.contains(packageName)) val appData = ApplicationData(it.loadIcon(pm), it.loadLabel(pm).toString(), packageName, currentlySelectedApps.contains(packageName))
@ -49,20 +55,22 @@ class AppListDialogFragment : DialogFragment() {
} }
}) })
} }
}
applicationData.sortWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.name }) applicationData.sortWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.name })
applicationData withContext(Dispatchers.Main) {
}.whenComplete { data, throwable ->
if (data != null) {
appData.clear() appData.clear()
appData.addAll(data) appData.addAll(applicationData)
} else { }
val error = ErrorMessages[throwable] } catch (e: Exception) {
withContext(Dispatchers.Main) {
val error = ErrorMessages[e]
val message = activity.getString(R.string.error_fetching_apps, error) val message = activity.getString(R.string.error_fetching_apps, error)
Toast.makeText(activity, message, Toast.LENGTH_LONG).show() Toast.makeText(activity, message, Toast.LENGTH_LONG).show()
dismissAllowingStateLoss() dismissAllowingStateLoss()
} }
} }
} }
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)

View File

@ -15,32 +15,31 @@ import com.wireguard.android.Application
import com.wireguard.android.R import com.wireguard.android.R
import com.wireguard.android.activity.SettingsActivity import com.wireguard.android.activity.SettingsActivity
import com.wireguard.android.util.ErrorMessages import com.wireguard.android.util.ErrorMessages
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlin.system.exitProcess import kotlin.system.exitProcess
class ModuleDownloaderPreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) { class ModuleDownloaderPreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) {
private var state = State.INITIAL private var state = State.INITIAL
private val coroutineScope = CoroutineScope(Dispatchers.Main)
override fun getSummary() = context.getString(state.messageResourceId) override fun getSummary() = context.getString(state.messageResourceId)
override fun getTitle() = context.getString(R.string.module_installer_title) override fun getTitle() = context.getString(R.string.module_installer_title)
@SuppressLint("ApplySharedPref")
override fun onClick() { override fun onClick() {
setState(State.WORKING) setState(State.WORKING)
Application.getAsyncWorker().supplyAsync(Application.getModuleLoader()::download).whenComplete(this::onDownloadResult) coroutineScope.launch {
} try {
when (withContext(Dispatchers.IO) { Application.getModuleLoader().download() }) {
@SuppressLint("ApplySharedPref") OsConstants.ENOENT -> setState(State.NOTFOUND)
private fun onDownloadResult(result: Int, throwable: Throwable?) { OsConstants.EXIT_SUCCESS -> {
when {
throwable != null -> {
setState(State.FAILURE)
Toast.makeText(context, ErrorMessages[throwable], Toast.LENGTH_LONG).show()
}
result == OsConstants.ENOENT -> setState(State.NOTFOUND)
result == OsConstants.EXIT_SUCCESS -> {
setState(State.SUCCESS) setState(State.SUCCESS)
Application.getSharedPreferences().edit().remove("disable_kernel_module").commit() Application.getSharedPreferences().edit().remove("disable_kernel_module").commit()
Application.getAsyncWorker().runAsync { CoroutineScope(Dispatchers.Default).launch {
val restartIntent = Intent(context, SettingsActivity::class.java) val restartIntent = Intent(context, SettingsActivity::class.java)
restartIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) restartIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
restartIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) restartIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
@ -50,6 +49,11 @@ class ModuleDownloaderPreference(context: Context, attrs: AttributeSet?) : Prefe
} }
else -> setState(State.FAILURE) else -> setState(State.FAILURE)
} }
} catch (e: Exception) {
setState(State.FAILURE)
Toast.makeText(context, ErrorMessages[e], Toast.LENGTH_LONG).show()
}
}
} }
private fun setState(state: State) { private fun setState(state: State) {

View File

@ -10,6 +10,10 @@ import androidx.preference.Preference
import com.wireguard.android.Application import com.wireguard.android.Application
import com.wireguard.android.R import com.wireguard.android.R
import com.wireguard.android.util.ToolsInstaller import com.wireguard.android.util.ToolsInstaller
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
/** /**
* Preference implementing a button that asynchronously runs `ToolsInstaller` and displays the * Preference implementing a button that asynchronously runs `ToolsInstaller` and displays the
@ -17,6 +21,7 @@ import com.wireguard.android.util.ToolsInstaller
*/ */
class ToolsInstallerPreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) { class ToolsInstallerPreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) {
private var state = State.INITIAL private var state = State.INITIAL
private val coroutineScope = CoroutineScope(Dispatchers.Main)
override fun getSummary() = context.getString(state.messageResourceId) override fun getSummary() = context.getString(state.messageResourceId)
@ -24,31 +29,36 @@ class ToolsInstallerPreference(context: Context, attrs: AttributeSet?) : Prefere
override fun onAttached() { override fun onAttached() {
super.onAttached() super.onAttached()
Application.getAsyncWorker().supplyAsync(Application.getToolsInstaller()::areInstalled).whenComplete(this::onCheckResult) coroutineScope.launch {
} try {
val state = withContext(Dispatchers.IO) { Application.getToolsInstaller().areInstalled() }
private fun onCheckResult(state: Int, throwable: Throwable?) {
when { when {
throwable != null || state == ToolsInstaller.ERROR -> setState(State.INITIAL) state == ToolsInstaller.ERROR -> setState(State.INITIAL)
state and ToolsInstaller.YES == ToolsInstaller.YES -> setState(State.ALREADY) state and ToolsInstaller.YES == ToolsInstaller.YES -> setState(State.ALREADY)
state and (ToolsInstaller.MAGISK or ToolsInstaller.NO) == ToolsInstaller.MAGISK or ToolsInstaller.NO -> setState(State.INITIAL_MAGISK) state and (ToolsInstaller.MAGISK or ToolsInstaller.NO) == ToolsInstaller.MAGISK or ToolsInstaller.NO -> setState(State.INITIAL_MAGISK)
state and (ToolsInstaller.SYSTEM or ToolsInstaller.NO) == ToolsInstaller.SYSTEM or ToolsInstaller.NO -> setState(State.INITIAL_SYSTEM) state and (ToolsInstaller.SYSTEM or ToolsInstaller.NO) == ToolsInstaller.SYSTEM or ToolsInstaller.NO -> setState(State.INITIAL_SYSTEM)
else -> setState(State.INITIAL) else -> setState(State.INITIAL)
} }
} catch (_: Exception) {
setState(State.INITIAL)
}
}
} }
override fun onClick() { override fun onClick() {
setState(State.WORKING) setState(State.WORKING)
Application.getAsyncWorker().supplyAsync { Application.getToolsInstaller().install() }.whenComplete { result: Int, throwable: Throwable? -> onInstallResult(result, throwable) } coroutineScope.launch {
} try {
val result = withContext(Dispatchers.IO) { Application.getToolsInstaller().install() }
private fun onInstallResult(result: Int, throwable: Throwable?) {
when { when {
throwable != null -> setState(State.FAILURE)
result and (ToolsInstaller.YES or ToolsInstaller.MAGISK) == ToolsInstaller.YES or ToolsInstaller.MAGISK -> setState(State.SUCCESS_MAGISK) result and (ToolsInstaller.YES or ToolsInstaller.MAGISK) == ToolsInstaller.YES or ToolsInstaller.MAGISK -> setState(State.SUCCESS_MAGISK)
result and (ToolsInstaller.YES or ToolsInstaller.SYSTEM) == ToolsInstaller.YES or ToolsInstaller.SYSTEM -> setState(State.SUCCESS_SYSTEM) result and (ToolsInstaller.YES or ToolsInstaller.SYSTEM) == ToolsInstaller.YES or ToolsInstaller.SYSTEM -> setState(State.SUCCESS_SYSTEM)
else -> setState(State.FAILURE) else -> setState(State.FAILURE)
} }
} catch (_: Exception) {
setState(State.FAILURE)
}
}
} }
private fun setState(state: State) { private fun setState(state: State) {

View File

@ -16,6 +16,10 @@ import com.wireguard.android.R
import com.wireguard.android.backend.Backend import com.wireguard.android.backend.Backend
import com.wireguard.android.backend.GoBackend import com.wireguard.android.backend.GoBackend
import com.wireguard.android.backend.WgQuickBackend import com.wireguard.android.backend.WgQuickBackend
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.Locale import java.util.Locale
class VersionPreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) { class VersionPreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) {
@ -45,11 +49,12 @@ class VersionPreference(context: Context, attrs: AttributeSet?) : Preference(con
init { init {
Application.getBackendAsync().thenAccept { backend -> Application.getBackendAsync().thenAccept { backend ->
versionSummary = getContext().getString(R.string.version_summary_checking, getBackendPrettyName(context, backend).toLowerCase(Locale.ENGLISH)) versionSummary = getContext().getString(R.string.version_summary_checking, getBackendPrettyName(context, backend).toLowerCase(Locale.ENGLISH))
Application.getAsyncWorker().supplyAsync(backend::getVersion).whenComplete { version, exception -> CoroutineScope(Dispatchers.Main).launch {
versionSummary = if (exception == null) versionSummary = try {
getContext().getString(R.string.version_summary, getBackendPrettyName(context, backend), version) getContext().getString(R.string.version_summary, getBackendPrettyName(context, backend), withContext(Dispatchers.IO) { backend.version })
else } catch (_: Exception) {
getContext().getString(R.string.version_summary_unknown, getBackendPrettyName(context, backend).toLowerCase(Locale.ENGLISH)) getContext().getString(R.string.version_summary_unknown, getBackendPrettyName(context, backend).toLowerCase(Locale.ENGLISH))
}
notifyChanged() notifyChanged()
} }
} }