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,11 +121,13 @@ 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,33 +37,37 @@ 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 {
val launcherIntent = Intent(Intent.ACTION_MAIN, null) try {
launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER) val applicationData: MutableList<ApplicationData> = ArrayList()
val resolveInfos = pm.queryIntentActivities(launcherIntent, 0) withContext(Dispatchers.IO) {
val applicationData: MutableList<ApplicationData> = ArrayList() val launcherIntent = Intent(Intent.ACTION_MAIN, null)
resolveInfos.forEach { launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER)
val packageName = it.activityInfo.packageName val resolveInfos = pm.queryIntentActivities(launcherIntent, 0)
val appData = ApplicationData(it.loadIcon(pm), it.loadLabel(pm).toString(), packageName, currentlySelectedApps.contains(packageName)) resolveInfos.forEach {
applicationData.add(appData) val packageName = it.activityInfo.packageName
appData.addOnPropertyChangedCallback(object : Observable.OnPropertyChangedCallback() { val appData = ApplicationData(it.loadIcon(pm), it.loadLabel(pm).toString(), packageName, currentlySelectedApps.contains(packageName))
override fun onPropertyChanged(sender: Observable?, propertyId: Int) { applicationData.add(appData)
if (propertyId == BR.selected) appData.addOnPropertyChangedCallback(object : Observable.OnPropertyChangedCallback() {
setButtonText() override fun onPropertyChanged(sender: Observable?, propertyId: Int) {
if (propertyId == BR.selected)
setButtonText()
}
})
} }
}) }
} applicationData.sortWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.name })
applicationData.sortWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.name }) withContext(Dispatchers.Main) {
applicationData appData.clear()
}.whenComplete { data, throwable -> appData.addAll(applicationData)
if (data != null) { }
appData.clear() } catch (e: Exception) {
appData.addAll(data) withContext(Dispatchers.Main) {
} else { val error = ErrorMessages[e]
val error = ErrorMessages[throwable] 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() }
} }
} }
} }

View File

@ -15,40 +15,44 @@ 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 { setState(State.SUCCESS)
throwable != null -> { Application.getSharedPreferences().edit().remove("disable_kernel_module").commit()
setState(State.FAILURE) CoroutineScope(Dispatchers.Default).launch {
Toast.makeText(context, ErrorMessages[throwable], Toast.LENGTH_LONG).show() val restartIntent = Intent(context, SettingsActivity::class.java)
} restartIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
result == OsConstants.ENOENT -> setState(State.NOTFOUND) restartIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
result == OsConstants.EXIT_SUCCESS -> { Application.get().startActivity(restartIntent)
setState(State.SUCCESS) exitProcess(0)
Application.getSharedPreferences().edit().remove("disable_kernel_module").commit() }
Application.getAsyncWorker().runAsync { }
val restartIntent = Intent(context, SettingsActivity::class.java) else -> setState(State.FAILURE)
restartIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
restartIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
Application.get().startActivity(restartIntent)
exitProcess(0)
} }
} catch (e: Exception) {
setState(State.FAILURE)
Toast.makeText(context, ErrorMessages[e], Toast.LENGTH_LONG).show()
} }
else -> setState(State.FAILURE)
} }
} }

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,30 +29,35 @@ 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 { state == ToolsInstaller.ERROR -> setState(State.INITIAL)
throwable != null || 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 { result and (ToolsInstaller.YES or ToolsInstaller.MAGISK) == ToolsInstaller.YES or ToolsInstaller.MAGISK -> setState(State.SUCCESS_MAGISK)
throwable != null -> setState(State.FAILURE) result and (ToolsInstaller.YES or ToolsInstaller.SYSTEM) == ToolsInstaller.YES or ToolsInstaller.SYSTEM -> setState(State.SUCCESS_SYSTEM)
result and (ToolsInstaller.YES or ToolsInstaller.MAGISK) == ToolsInstaller.YES or ToolsInstaller.MAGISK -> setState(State.SUCCESS_MAGISK) else -> setState(State.FAILURE)
result and (ToolsInstaller.YES or ToolsInstaller.SYSTEM) == ToolsInstaller.YES or ToolsInstaller.SYSTEM -> setState(State.SUCCESS_SYSTEM) }
else -> setState(State.FAILURE) } catch (_: Exception) {
setState(State.FAILURE)
}
} }
} }

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()
} }
} }