Prevent initiailizing su in main thread

This should hopefully fix #113.
This commit is contained in:
Mygod
2019-07-16 10:23:21 +08:00
parent 983e80596b
commit f61f694d5f
6 changed files with 157 additions and 122 deletions

View File

@@ -21,6 +21,10 @@ import be.mygod.vpnhotspot.util.RootSession
import be.mygod.vpnhotspot.util.launchUrl
import be.mygod.vpnhotspot.widget.SmartSnackbar
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.io.File
import java.io.IOException
@@ -40,14 +44,22 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
if (Build.VERSION.SDK_INT >= 27) {
isChecked = TetherOffloadManager.enabled
setOnPreferenceChangeListener { _, newValue ->
try {
TetherOffloadManager.enabled = newValue as Boolean
TetherOffloadManager.enabled == newValue
} catch (e: Exception) {
Timber.d(e)
SmartSnackbar.make(e).show()
false
if (TetherOffloadManager.enabled != newValue) {
isEnabled = false
GlobalScope.launch {
try {
TetherOffloadManager.enabled = newValue as Boolean
} catch (e: Exception) {
Timber.d(e)
SmartSnackbar.make(e).show()
}
withContext(Dispatchers.Main) {
isChecked = TetherOffloadManager.enabled
isEnabled = true
}
}
}
false
}
} else parent!!.removePreference(this)
}
@@ -60,82 +72,86 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
boot.isChecked = BootReceiver.enabled
} else boot.parent!!.removePreference(boot)
findPreference<Preference>("service.clean")!!.setOnPreferenceClickListener {
RoutingManager.clean()
GlobalScope.launch { RoutingManager.clean() }
true
}
findPreference<Preference>(IpMonitor.KEY)!!.setOnPreferenceChangeListener { _, _ ->
Snackbar.make(requireView(), R.string.settings_restart_required, Snackbar.LENGTH_LONG).apply {
setAction(R.string.settings_exit_app) {
RoutingManager.clean(false)
RootSession.trimMemory()
exitProcess(0)
GlobalScope.launch {
RoutingManager.clean(false)
RootSession.trimMemory()
exitProcess(0)
}
}
}.show()
true
}
findPreference<Preference>("misc.logcat")!!.setOnPreferenceClickListener {
val context = requireContext()
val logDir = File(context.cacheDir, "log")
logDir.mkdir()
val logFile = File.createTempFile("vpnhotspot-", ".log", logDir)
logFile.outputStream().use { out ->
PrintWriter(out.bufferedWriter()).use { writer ->
writer.println("${BuildConfig.VERSION_CODE} is running on API ${Build.VERSION.SDK_INT}\n")
writer.flush()
try {
Runtime.getRuntime().exec(arrayOf("logcat", "-d")).inputStream.use { it.copyTo(out) }
} catch (e: IOException) {
Timber.w(e)
}
writer.println()
val commands = StringBuilder()
// https://android.googlesource.com/platform/external/iptables/+/android-7.0.0_r1/iptables/Android.mk#34
val iptablesSave = if (Build.VERSION.SDK_INT >= 24) "iptables-save" else
File(app.deviceStorage.cacheDir, "iptables-save").absolutePath.also {
commands.appendln("ln -sf /system/bin/iptables $it")
GlobalScope.launch(Dispatchers.IO) {
val context = requireContext()
val logDir = File(context.cacheDir, "log")
logDir.mkdir()
val logFile = File.createTempFile("vpnhotspot-", ".log", logDir)
logFile.outputStream().use { out ->
PrintWriter(out.bufferedWriter()).use { writer ->
writer.println("${BuildConfig.VERSION_CODE} is running on API ${Build.VERSION.SDK_INT}\n")
writer.flush()
try {
Runtime.getRuntime().exec(arrayOf("logcat", "-d")).inputStream.use { it.copyTo(out) }
} catch (e: IOException) {
Timber.w(e)
}
writer.println()
val commands = StringBuilder()
// https://android.googlesource.com/platform/external/iptables/+/android-7.0.0_r1/iptables/Android.mk#34
val iptablesSave = if (Build.VERSION.SDK_INT >= 24) "iptables-save" else
File(app.deviceStorage.cacheDir, "iptables-save").absolutePath.also {
commands.appendln("ln -sf /system/bin/iptables $it")
}
commands.append("""
|echo dumpsys ${Context.WIFI_P2P_SERVICE}
|dumpsys ${Context.WIFI_P2P_SERVICE}
|echo
|echo dumpsys ${Context.CONNECTIVITY_SERVICE} tethering
|dumpsys ${Context.CONNECTIVITY_SERVICE} tethering
|echo
|echo iptables -t filter
|$iptablesSave -t filter
|echo
|echo iptables -t nat
|$iptablesSave -t nat
|echo
|echo ip rule
|ip rule
|echo
|echo ip neigh
|ip neigh
|echo
|echo iptables -nvx -L vpnhotspot_fwd
|$IPTABLES -nvx -L vpnhotspot_fwd
|echo
|echo iptables -nvx -L vpnhotspot_acl
|$IPTABLES -nvx -L vpnhotspot_acl
|echo
|echo logcat-su
|logcat -d
""".trimMargin())
try {
RootSession.use { it.execQuiet(commands.toString(), true).out.forEach(writer::println) }
} catch (e: Exception) {
e.printStackTrace(writer)
Timber.i(e)
}
commands.append("""
|echo dumpsys ${Context.WIFI_P2P_SERVICE}
|dumpsys ${Context.WIFI_P2P_SERVICE}
|echo
|echo dumpsys ${Context.CONNECTIVITY_SERVICE} tethering
|dumpsys ${Context.CONNECTIVITY_SERVICE} tethering
|echo
|echo iptables -t filter
|$iptablesSave -t filter
|echo
|echo iptables -t nat
|$iptablesSave -t nat
|echo
|echo ip rule
|ip rule
|echo
|echo ip neigh
|ip neigh
|echo
|echo iptables -nvx -L vpnhotspot_fwd
|$IPTABLES -nvx -L vpnhotspot_fwd
|echo
|echo iptables -nvx -L vpnhotspot_acl
|$IPTABLES -nvx -L vpnhotspot_acl
|echo
|echo logcat-su
|logcat -d
""".trimMargin())
try {
RootSession.use { it.execQuiet(commands.toString(), true).out.forEach(writer::println) }
} catch (e: Exception) {
e.printStackTrace(writer)
Timber.i(e)
}
}
context.startActivity(Intent.createChooser(Intent(Intent.ACTION_SEND)
.setType("text/x-log")
.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
.putExtra(Intent.EXTRA_STREAM,
FileProvider.getUriForFile(context, "be.mygod.vpnhotspot.log", logFile)),
context.getString(R.string.abc_shareactionprovider_share_with)))
}
startActivity(Intent.createChooser(Intent(Intent.ACTION_SEND)
.setType("text/x-log")
.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
.putExtra(Intent.EXTRA_STREAM,
FileProvider.getUriForFile(context, "be.mygod.vpnhotspot.log", logFile)),
getString(R.string.abc_shareactionprovider_share_with)))
true
}
findPreference<Preference>("misc.source")!!.setOnPreferenceClickListener {