Merge branch 'master' into temp-hotspot-use-system

This commit is contained in:
Mygod
2023-03-02 23:19:51 -05:00
148 changed files with 3939 additions and 3409 deletions

View File

@@ -1,7 +1,6 @@
package be.mygod.vpnhotspot.root
import android.content.Context
import android.os.Build
import android.os.Parcelable
import android.os.RemoteException
import android.provider.Settings
@@ -30,18 +29,10 @@ fun ProcessBuilder.fixPath(redirect: Boolean = false) = apply {
@Parcelize
data class Dump(val path: String, val cacheDir: File = app.deviceStorage.codeCacheDir) : RootCommandNoResult {
@Suppress("BlockingMethodInNonBlockingContext")
override suspend fun execute() = withContext(Dispatchers.IO) {
FileOutputStream(path, true).use { out ->
val process = ProcessBuilder("sh").fixPath(true).start()
process.outputStream.bufferedWriter().use { commands ->
// https://android.googlesource.com/platform/external/iptables/+/android-7.0.0_r1/iptables/Android.mk#34
val iptablesSave = if (Build.VERSION.SDK_INT < 24) File(cacheDir, "iptables-save").absolutePath.also {
commands.appendLine("ln -sf /system/bin/iptables $it")
} else "iptables-save"
val ip6tablesSave = if (Build.VERSION.SDK_INT < 24) File(cacheDir, "ip6tables-save").absolutePath.also {
commands.appendLine("ln -sf /system/bin/ip6tables $it")
} else "ip6tables-save"
commands.appendLine("""
|echo dumpsys ${Context.WIFI_P2P_SERVICE}
|dumpsys ${Context.WIFI_P2P_SERVICE}
@@ -50,13 +41,13 @@ data class Dump(val path: String, val cacheDir: File = app.deviceStorage.codeCac
|dumpsys ${Context.CONNECTIVITY_SERVICE} tethering
|echo
|echo iptables -t filter
|$iptablesSave -t filter
|iptables-save -t filter
|echo
|echo iptables -t nat
|$iptablesSave -t nat
|iptables-save -t nat
|echo
|echo ip6tables-save
|$ip6tablesSave
|ip6tables-save
|echo
|echo ip rule
|$IP rule
@@ -125,7 +116,7 @@ class ProcessListener(private val terminateRegex: Regex,
parent.join()
} finally {
parent.cancel()
if (Build.VERSION.SDK_INT < 26) process.destroy() else if (process.isAlive) process.destroyForcibly()
if (process.isAlive) process.destroyForcibly()
parent.join()
}
}
@@ -162,7 +153,6 @@ data class StartTethering(private val type: Int,
@Deprecated("Old API since API 30")
@Parcelize
@RequiresApi(24)
@Suppress("DEPRECATION")
data class StartTetheringLegacy(private val cacheDir: File, private val type: Int,
private val showProvisioningUi: Boolean) : RootCommand<ParcelableBoolean> {
@@ -184,7 +174,6 @@ data class StartTetheringLegacy(private val cacheDir: File, private val type: In
}
@Parcelize
@RequiresApi(24)
data class StopTethering(private val type: Int) : RootCommandNoResult {
override suspend fun execute(): Parcelable? {
TetheringManager.stopTethering(type)
@@ -209,12 +198,11 @@ data class SettingsGlobalPut(val name: String, val value: String) : RootCommandN
}
}
@Suppress("BlockingMethodInNonBlockingContext")
override suspend fun execute() = withContext(Dispatchers.IO) {
val process = ProcessBuilder("settings", "put", "global", name, value).fixPath(true).start()
val error = process.inputStream.bufferedReader().readText()
check(process.waitFor() == 0)
if (error.isNotEmpty()) throw RemoteException(error)
val exit = process.waitFor()
if (exit != 0 || error.isNotEmpty()) throw RemoteException("Process exited with $exit: $error")
null
}
}

View File

@@ -1,5 +1,7 @@
package be.mygod.vpnhotspot.root
import android.net.MacAddress
import android.net.wifi.ScanResult
import android.net.wifi.p2p.WifiP2pManager
import android.os.Looper
import android.os.Parcelable
@@ -11,6 +13,7 @@ import be.mygod.librootkotlinx.*
import be.mygod.vpnhotspot.net.wifi.WifiP2pManagerHelper.deletePersistentGroup
import be.mygod.vpnhotspot.net.wifi.WifiP2pManagerHelper.requestDeviceAddress
import be.mygod.vpnhotspot.net.wifi.WifiP2pManagerHelper.requestPersistentGroupInfo
import be.mygod.vpnhotspot.net.wifi.WifiP2pManagerHelper.setVendorElements
import be.mygod.vpnhotspot.net.wifi.WifiP2pManagerHelper.setWifiP2pChannels
import be.mygod.vpnhotspot.util.Services
import kotlinx.parcelize.Parcelize
@@ -35,10 +38,8 @@ object RepeaterCommands {
@Parcelize
@RequiresApi(29)
class RequestDeviceAddress : RootCommand<ParcelableLong?> {
override suspend fun execute() = Services.p2p!!.run {
requestDeviceAddress(obtainChannel())?.let { ParcelableLong(it.addr) }
}
class RequestDeviceAddress : RootCommand<MacAddress?> {
override suspend fun execute() = Services.p2p!!.run { requestDeviceAddress(obtainChannel()) }
}
@Parcelize
@@ -55,6 +56,14 @@ object RepeaterCommands {
}
}
@Parcelize
@RequiresApi(33)
data class SetVendorElements(private val ve: List<ScanResult.InformationElement>) : RootCommand<ParcelableInt?> {
override suspend fun execute() = Services.p2p!!.run {
setVendorElements(obtainChannel(), ve)?.let { ParcelableInt(it) }
}
}
@Parcelize
data class WriteP2pConfig(val data: String, val legacy: Boolean) : RootCommandNoResult {
override suspend fun execute(): Parcelable? {

View File

@@ -6,6 +6,8 @@ import android.util.Log
import be.mygod.librootkotlinx.*
import be.mygod.vpnhotspot.App.Companion.app
import be.mygod.vpnhotspot.util.Services
import be.mygod.vpnhotspot.util.UnblockCentral
import com.google.firebase.crashlytics.FirebaseCrashlytics
import kotlinx.parcelize.Parcelize
import timber.log.Timber
@@ -31,6 +33,7 @@ object RootManager : RootSession(), Logger {
})
Logger.me = RootManager
Services.init { systemContext }
UnblockCentral.needInit = false
return null
}
}
@@ -42,7 +45,10 @@ object RootManager : RootSession(), Logger {
override suspend fun initServer(server: RootServer) {
Logger.me = this
server.init(app.deviceStorage)
AppProcess.shouldRelocateHeuristics.let {
FirebaseCrashlytics.getInstance().setCustomKey("RootManager.relocateEnabled", it)
server.init(app.deviceStorage, it)
}
server.execute(RootInit())
}
}

View File

@@ -2,7 +2,7 @@ package be.mygod.vpnhotspot.root
import android.os.Parcelable
import be.mygod.librootkotlinx.RootCommand
import be.mygod.librootkotlinx.RootCommandOneWay
import be.mygod.librootkotlinx.RootCommandNoResult
import be.mygod.vpnhotspot.net.Routing
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
@@ -13,8 +13,7 @@ import timber.log.Timber
object RoutingCommands {
@Parcelize
class Clean : RootCommandOneWay {
@Suppress("BlockingMethodInNonBlockingContext")
class Clean : RootCommandNoResult {
override suspend fun execute() = withContext(Dispatchers.IO) {
val process = ProcessBuilder("sh").fixPath(true).start()
process.outputStream.bufferedWriter().use(Routing.Companion::appendCleanCommands)
@@ -23,6 +22,7 @@ object RoutingCommands {
else -> Timber.w("Unexpected exit code $code")
}
check(process.waitFor() == 0)
null
}
}

View File

@@ -1,13 +1,19 @@
package be.mygod.vpnhotspot.root
import android.annotation.TargetApi
import android.content.ClipData
import android.net.wifi.SoftApConfiguration
import android.net.wifi.WifiManager
import android.os.Build
import android.os.Parcelable
import androidx.annotation.RequiresApi
import be.mygod.librootkotlinx.ParcelableBoolean
import be.mygod.librootkotlinx.RootCommand
import be.mygod.librootkotlinx.RootCommandChannel
import be.mygod.vpnhotspot.net.wifi.SoftApConfigurationCompat
import be.mygod.vpnhotspot.App.Companion.app
import be.mygod.vpnhotspot.R
import be.mygod.vpnhotspot.net.wifi.WifiApManager
import be.mygod.vpnhotspot.net.wifi.WifiClient
import be.mygod.vpnhotspot.widget.SmartSnackbar
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
@@ -15,7 +21,6 @@ import kotlinx.parcelize.Parcelize
import timber.log.Timber
object WifiApCommands {
@RequiresApi(28)
sealed class SoftApCallbackParcel : Parcelable {
abstract fun dispatch(callback: WifiApManager.SoftApCallbackCompat)
@@ -55,7 +60,6 @@ object WifiApCommands {
}
@Parcelize
@RequiresApi(28)
class RegisterSoftApCallback : RootCommandChannel<SoftApCallbackParcel> {
override fun create(scope: CoroutineScope) = scope.produce(capacity = capacity) {
val finish = CompletableDeferred<Unit>()
@@ -111,7 +115,6 @@ object WifiApCommands {
private val callbacks = mutableSetOf<WifiApManager.SoftApCallbackCompat>()
private val lastCallback = AutoFiringCallbacks()
private var rootCallbackJob: Job? = null
@RequiresApi(28)
private suspend fun handleChannel(channel: ReceiveChannel<SoftApCallbackParcel>) = channel.consumeEach { parcel ->
when (parcel) {
is SoftApCallbackParcel.OnStateChanged -> synchronized(callbacks) { lastCallback.state = parcel }
@@ -121,10 +124,22 @@ object WifiApCommands {
}
is SoftApCallbackParcel.OnInfoChanged -> synchronized(callbacks) { lastCallback.info = parcel }
is SoftApCallbackParcel.OnCapabilityChanged -> synchronized(callbacks) { lastCallback.capability = parcel }
is SoftApCallbackParcel.OnBlockedClientConnecting -> @TargetApi(30) { // passively consume events
val client = WifiClient(parcel.client)
val macAddress = client.macAddress
var name = macAddress.toString()
if (Build.VERSION.SDK_INT >= 31) client.apInstanceIdentifier?.let { name += "%$it" }
val reason = WifiApManager.clientBlockLookup(parcel.blockedReason, true)
Timber.i("$name blocked from connecting: $reason (${parcel.blockedReason})")
SmartSnackbar.make(app.getString(R.string.tethering_manage_wifi_client_blocked, name, reason)).apply {
action(R.string.tethering_manage_wifi_copy_mac) {
app.clipboard.setPrimaryClip(ClipData.newPlainText(null, macAddress.toString()))
}
}.show()
}
}
for (callback in synchronized(callbacks) { callbacks.toList() }) parcel.dispatch(callback)
}
@RequiresApi(28)
fun registerSoftApCallback(callback: WifiApManager.SoftApCallbackCompat) = synchronized(callbacks) {
val wasEmpty = callbacks.isEmpty()
callbacks.add(callback)
@@ -141,7 +156,6 @@ object WifiApCommands {
null
} else lastCallback
}?.toSequence()?.forEach { it?.dispatch(callback) }
@RequiresApi(28)
fun unregisterSoftApCallback(callback: WifiApManager.SoftApCallbackCompat) = synchronized(callbacks) {
if (callbacks.remove(callback) && callbacks.isEmpty()) {
rootCallbackJob!!.cancel()
@@ -150,13 +164,29 @@ object WifiApCommands {
}
@Parcelize
class GetConfiguration : RootCommand<SoftApConfigurationCompat> {
override suspend fun execute() = WifiApManager.configurationCompat
@Deprecated("Use GetConfiguration instead", ReplaceWith("GetConfiguration"))
@Suppress("DEPRECATION")
class GetConfigurationLegacy : RootCommand<android.net.wifi.WifiConfiguration?> {
override suspend fun execute() = WifiApManager.configurationLegacy
}
@Parcelize
@RequiresApi(30)
class GetConfiguration : RootCommand<SoftApConfiguration> {
override suspend fun execute() = WifiApManager.configuration
}
@Parcelize
data class SetConfiguration(val configuration: SoftApConfigurationCompat) : RootCommand<ParcelableBoolean> {
override suspend fun execute() = ParcelableBoolean(WifiApManager.setConfigurationCompat(configuration))
@Deprecated("Use SetConfiguration instead", ReplaceWith("SetConfiguration"))
@Suppress("DEPRECATION")
data class SetConfigurationLegacy(
val configuration: android.net.wifi.WifiConfiguration?,
) : RootCommand<ParcelableBoolean> {
override suspend fun execute() = ParcelableBoolean(WifiApManager.setConfiguration(configuration))
}
@Parcelize
@RequiresApi(30)
data class SetConfiguration(val configuration: SoftApConfiguration) : RootCommand<ParcelableBoolean> {
override suspend fun execute() = ParcelableBoolean(WifiApManager.setConfiguration(configuration))
}
@Parcelize