Fix crashes

This commit is contained in:
Mygod
2020-07-03 10:55:21 +08:00
parent 4b1101f41e
commit 05c4ba5b81
10 changed files with 37 additions and 28 deletions

View File

@@ -68,7 +68,7 @@ class App : Application() {
} else {
if (priority >= Log.WARN || priority == Log.DEBUG) {
Log.println(priority, tag, message)
Log.d(tag, message, t)
Log.w(tag, message, t)
}
if (priority >= Log.INFO && t !is NoShellException) {
FirebaseCrashlytics.getInstance().recordException(t)

View File

@@ -76,7 +76,7 @@ class RepeaterService : Service(), CoroutineScope, WifiP2pManager.ChannelListene
set(value) = app.pref.edit { putString(KEY_PASSPHRASE, value) }
var operatingBand: Int
@SuppressLint("InlinedApi")
get() = app.pref.getInt(KEY_OPERATING_BAND, WifiP2pConfig.GROUP_OWNER_BAND_AUTO)
get() = app.pref.getInt(KEY_OPERATING_BAND, SoftApConfigurationCompat.BAND_ANY)
set(value) = app.pref.edit { putInt(KEY_OPERATING_BAND, value) }
var operatingChannel: Int
get() {
@@ -366,11 +366,11 @@ class RepeaterService : Service(), CoroutineScope, WifiP2pManager.ChannelListene
setNetworkName(PLACEHOLDER_NETWORK_NAME)
setPassphrase(passphrase)
operatingChannel.let { oc ->
if (oc == 0) setGroupOperatingBand(when (operatingBand) {
if (oc == 0) setGroupOperatingBand(when (val band = operatingBand) {
SoftApConfigurationCompat.BAND_ANY -> WifiP2pConfig.GROUP_OWNER_BAND_AUTO
SoftApConfigurationCompat.BAND_2GHZ -> WifiP2pConfig.GROUP_OWNER_BAND_2GHZ
SoftApConfigurationCompat.BAND_5GHZ -> WifiP2pConfig.GROUP_OWNER_BAND_5GHZ
else -> throw IllegalArgumentException("Unknown band")
else -> throw IllegalArgumentException("Unknown band $band")
})
else setGroupOperatingFrequency(SoftApConfigurationCompat.channelToFrequency(operatingBand, oc))
}

View File

@@ -67,7 +67,7 @@ enum class TetherType(@DrawableRes val icon: Int) {
@RequiresApi(30)
override fun onTetherableInterfaceRegexpsChanged(args: Array<out Any?>?) = synchronized(this) {
if (requiresUpdate) return@synchronized
Timber.i("onTetherableInterfaceRegexpsChanged: ${args?.contentToString()}")
Timber.i("onTetherableInterfaceRegexpsChanged: ${args?.contentDeepToString()}")
TetheringManager.unregisterTetheringEventCallback(this)
requiresUpdate = true
listener()

View File

@@ -605,12 +605,12 @@ object TetheringManager {
*/
fun getLastTetherError(iface: String): Int = getLastTetherError(Services.connectivity, iface) as Int
val tetherErrorLookup = ConstantLookup(clazz, "TETHER_ERROR_",
val tetherErrorLookup = ConstantLookup("TETHER_ERROR_",
"TETHER_ERROR_NO_ERROR", "TETHER_ERROR_UNKNOWN_IFACE", "TETHER_ERROR_SERVICE_UNAVAIL",
"TETHER_ERROR_UNSUPPORTED", "TETHER_ERROR_UNAVAIL_IFACE", "TETHER_ERROR_MASTER_ERROR",
"TETHER_ERROR_TETHER_IFACE_ERROR", "TETHER_ERROR_UNTETHER_IFACE_ERROR", "TETHER_ERROR_ENABLE_NAT_ERROR",
"TETHER_ERROR_DISABLE_NAT_ERROR", "TETHER_ERROR_IFACE_CFG_ERROR", "TETHER_ERROR_PROVISION_FAILED",
"TETHER_ERROR_DHCPSERVER_ERROR", "TETHER_ERROR_ENTITLEMENT_UNKNOWN")
"TETHER_ERROR_DHCPSERVER_ERROR", "TETHER_ERROR_ENTITLEMENT_UNKNOWN") { clazz }
val Intent.tetheredIfaces get() = getStringArrayListExtra(
if (Build.VERSION.SDK_INT >= 26) EXTRA_ACTIVE_TETHER else EXTRA_ACTIVE_TETHER_LEGACY)

View File

@@ -117,7 +117,7 @@ object WifiApManager {
private val getFrequency by lazy { classSoftApInfo.getDeclaredMethod("getFrequency") }
private val getBandwidth by lazy { classSoftApInfo.getDeclaredMethod("getBandwidth") }
@RequiresApi(30)
val channelWidthLookup = ConstantLookup(classSoftApInfo, "CHANNEL_WIDTH_")
val channelWidthLookup = ConstantLookup("CHANNEL_WIDTH_") { classSoftApInfo }
const val CHANNEL_WIDTH_INVALID = 0
private val classSoftApCapability by lazy { Class.forName("android.net.wifi.SoftApCapability") }
@@ -125,15 +125,16 @@ object WifiApManager {
private val areFeaturesSupported by lazy {
classSoftApCapability.getDeclaredMethod("areFeaturesSupported", Long::class.java)
}
@RequiresApi(30)
val featureLookup = LongConstantLookup(classSoftApCapability, "SOFTAP_FEATURE_")
@get:RequiresApi(30)
val featureLookup by lazy { LongConstantLookup(classSoftApCapability, "SOFTAP_FEATURE_") }
private val methods29 = setOf("onStateChanged", "onNumClientsChanged")
@RequiresApi(28)
fun registerSoftApCallback(callback: SoftApCallbackCompat, executor: Executor): Any {
val proxy = Proxy.newProxyInstance(interfaceSoftApCallback.classLoader,
arrayOf(interfaceSoftApCallback), object : InvocationHandler {
override fun invoke(proxy: Any, method: Method, args: Array<out Any?>?): Any? {
return if (Build.VERSION.SDK_INT >= 30) invokeActual(proxy, method, args) else {
return if (Build.VERSION.SDK_INT >= 30 || method.name !in methods29) invokeActual(proxy, method, args) else {
executor.execute { invokeActual(proxy, method, args) }
null // no return value as of API 30
}

View File

@@ -7,10 +7,11 @@ import be.mygod.vpnhotspot.App.Companion.app
import be.mygod.vpnhotspot.R
import timber.log.Timber
class ConstantLookup(private val clazz: Class<*>, private val prefix: String, private val lookup29: Array<out String>) {
class ConstantLookup(private val prefix: String, private val lookup29: Array<out String>,
private val clazz: () -> Class<*>) {
private val lookup by lazy {
SparseArrayCompat<String>().apply {
for (field in clazz.declaredFields) try {
for (field in clazz().declaredFields) try {
if (field.name.startsWith(prefix)) put(field.getInt(null), field.name)
} catch (e: Exception) {
Timber.w(e)
@@ -30,10 +31,11 @@ class ConstantLookup(private val clazz: Class<*>, private val prefix: String, pr
}
@Suppress("FunctionName")
fun ConstantLookup(clazz: Class<*>, prefix: String, vararg lookup29: String) = ConstantLookup(clazz, prefix, lookup29)
fun ConstantLookup(prefix: String, vararg lookup29: String, clazz: () -> Class<*>) =
ConstantLookup(prefix, lookup29, clazz)
@Suppress("FunctionName")
inline fun <reified T> ConstantLookup(prefix: String, vararg lookup29: String) =
ConstantLookup(T::class.java, prefix, lookup29)
ConstantLookup(prefix, lookup29) { T::class.java }
class LongConstantLookup(private val clazz: Class<*>, private val prefix: String) {
private val lookup = LongSparseArray<String>().apply {

View File

@@ -22,6 +22,7 @@ import androidx.fragment.app.FragmentManager
import be.mygod.vpnhotspot.App.Companion.app
import be.mygod.vpnhotspot.net.MacAddressCompat
import be.mygod.vpnhotspot.widget.SmartSnackbar
import timber.log.Timber
import java.lang.invoke.MethodHandles
import java.lang.reflect.InvocationHandler
import java.lang.reflect.InvocationTargetException
@@ -134,12 +135,15 @@ private val newLookup by lazy @TargetApi(26) {
*
* See also: https://stackoverflow.com/a/49532463/2245107
*/
fun InvocationHandler.callSuper(interfaceClass: Class<*>, proxy: Any, method: Method, args: Array<out Any?>?) = when {
Build.VERSION.SDK_INT >= 26 -> newLookup.newInstance(interfaceClass, 0xf) // ALL_MODES
fun InvocationHandler.callSuper(interfaceClass: Class<*>, proxy: Any, method: Method, args: Array<out Any?>?): Any? {
return if (Build.VERSION.SDK_INT >= 26 && method.isDefault) newLookup.newInstance(interfaceClass, 0xf) // ALL_MODES
.`in`(interfaceClass).unreflectSpecial(method, interfaceClass).bindTo(proxy).run {
if (args == null) invokeWithArguments() else invokeWithArguments(*args)
}
// only Java 8+ has default interface methods; otherwise, we just redispatch it to InvocationHandler
args == null -> method(this)
else -> method(this, *args)
} else if (method.declaringClass === Object::class.java) {
// otherwise, we just redispatch it to InvocationHandler
if (args == null) method(this) else method(this, *args)
} else {
Timber.w("Unhandled method: $method(${args?.contentDeepToString()})")
null
}
}