From 4f97f9bf744f81fb606d310721d18b735dcdfa57 Mon Sep 17 00:00:00 2001 From: Mygod Date: Fri, 3 Jul 2020 08:10:23 +0800 Subject: [PATCH] Implement ConstantLookup --- .../mygod/vpnhotspot/manage/TetherManager.kt | 6 ++-- .../vpnhotspot/manage/TetheringTileService.kt | 2 +- .../mygod/vpnhotspot/net/TetheringManager.kt | 33 ++++--------------- .../vpnhotspot/net/wifi/WifiApManager.kt | 26 ++------------- .../mygod/vpnhotspot/util/ConstantLookup.kt | 33 +++++++++++++++++++ 5 files changed, 46 insertions(+), 54 deletions(-) create mode 100644 mobile/src/main/java/be/mygod/vpnhotspot/util/ConstantLookup.kt diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetherManager.kt b/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetherManager.kt index ee1fbc73..d6981ae2 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetherManager.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetherManager.kt @@ -88,7 +88,7 @@ sealed class TetherManager(protected val parent: TetheringFragment) : Manager(), override fun onTetheringStarted() = data.notifyChange() override fun onTetheringFailed(error: Int?) { Timber.d("onTetheringFailed: $error") - error?.let { SmartSnackbar.make("$tetherType: ${TetheringManager.tetherErrorMessage(it)}").show() } + error?.let { SmartSnackbar.make("$tetherType: ${TetheringManager.tetherErrorLookup(it)}").show() } data.notifyChange() } override fun onException(e: Exception) { @@ -108,7 +108,7 @@ sealed class TetherManager(protected val parent: TetheringFragment) : Manager(), val interested = errored.filter { TetherType.ofInterface(it) == tetherType } baseError = if (interested.isEmpty()) null else interested.joinToString("\n") { iface -> "$iface: " + try { - TetheringManager.tetherErrorMessage(TetheringManager.getLastTetherError(iface)) + TetheringManager.tetherErrorLookup(TetheringManager.getLastTetherError(iface)) } catch (e: InvocationTargetException) { if (Build.VERSION.SDK_INT !in 24..25 || e.cause !is SecurityException) Timber.w(e) else Timber.d(e) e.readableMessage @@ -149,7 +149,7 @@ sealed class TetherManager(protected val parent: TetheringFragment) : Manager(), override val title get() = parent.getString(R.string.tethering_manage_wifi) override val tetherType get() = TetherType.WIFI override val type get() = VIEW_TYPE_WIFI - override val text get() = listOfNotNull(failureReason?.let { WifiApManager.failureReason(it) }, + override val text get() = listOfNotNull(failureReason?.let { WifiApManager.failureReasonLookup(it) }, baseError).joinToString("\n") override fun start() = TetheringManager.startTethering(TetheringManager.TETHERING_WIFI, true, this) diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetheringTileService.kt b/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetheringTileService.kt index 2ced8548..86488ab2 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetheringTileService.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetheringTileService.kt @@ -118,7 +118,7 @@ sealed class TetheringTileService : IpNeighbourMonitoringTileService(), Tetherin override fun onTetheringStarted() = updateTile() override fun onTetheringFailed(error: Int?) { Timber.d("onTetheringFailed: $error") - error?.let { Toast.makeText(this, TetheringManager.tetherErrorMessage(it), Toast.LENGTH_LONG).show() } + error?.let { Toast.makeText(this, TetheringManager.tetherErrorLookup(it), Toast.LENGTH_LONG).show() } updateTile() } override fun onException(e: Exception) { diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/net/TetheringManager.kt b/mobile/src/main/java/be/mygod/vpnhotspot/net/TetheringManager.kt index 7413a13f..0976c36b 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/net/TetheringManager.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/net/TetheringManager.kt @@ -12,9 +12,7 @@ import android.net.Network import android.os.Build import android.os.Handler import androidx.annotation.RequiresApi -import androidx.collection.SparseArrayCompat import be.mygod.vpnhotspot.App.Companion.app -import be.mygod.vpnhotspot.R import be.mygod.vpnhotspot.root.RootManager import be.mygod.vpnhotspot.root.StartTethering import be.mygod.vpnhotspot.root.StopTethering @@ -607,31 +605,12 @@ object TetheringManager { */ fun getLastTetherError(iface: String): Int = getLastTetherError(Services.connectivity, iface) as Int - // tether errors defined in ConnectivityManager up to Android 10 - private val tetherErrors29 = arrayOf("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") - @get:RequiresApi(30) - private val tetherErrors by lazy { - SparseArrayCompat().apply { - for (field in clazz.declaredFields) try { - // all TETHER_ERROR_* are system-api since API 30 - if (field.name.startsWith("TETHER_ERROR_")) put(field.get(null) as Int, field.name) - } catch (e: Exception) { - Timber.w(e) - } - } - } - fun tetherErrorMessage(error: Int): String { - if (Build.VERSION.SDK_INT >= 30) try { - tetherErrors.get(error)?.let { return it } - } catch (e: ReflectiveOperationException) { - Timber.w(e) - } - return tetherErrors29.getOrNull(error) ?: app.getString(R.string.failure_reason_unknown, error) - } + val tetherErrorLookup = ConstantLookup(clazz, "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") val Intent.tetheredIfaces get() = getStringArrayListExtra( if (Build.VERSION.SDK_INT >= 26) EXTRA_ACTIVE_TETHER else EXTRA_ACTIVE_TETHER_LEGACY) diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/WifiApManager.kt b/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/WifiApManager.kt index 2b3de011..215c03b6 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/WifiApManager.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/WifiApManager.kt @@ -8,15 +8,12 @@ import android.net.wifi.SoftApConfiguration import android.net.wifi.WifiManager import android.os.Build import android.os.Handler -import android.os.Looper import androidx.annotation.RequiresApi -import androidx.collection.SparseArrayCompat import be.mygod.vpnhotspot.App.Companion.app -import be.mygod.vpnhotspot.R import be.mygod.vpnhotspot.net.wifi.SoftApConfigurationCompat.Companion.toCompat +import be.mygod.vpnhotspot.util.ConstantLookup import be.mygod.vpnhotspot.util.Services import be.mygod.vpnhotspot.util.callSuper -import be.mygod.vpnhotspot.util.makeExecutor import timber.log.Timber import java.lang.reflect.InvocationHandler import java.lang.reflect.Method @@ -96,25 +93,8 @@ object WifiApManager { @RequiresApi(30) fun onBlockedClientConnecting(client: MacAddress, blockedReason: Int) { } } - private val startFailures29 = arrayOf("SAP_START_FAILURE_GENERAL", "SAP_START_FAILURE_NO_CHANNEL") - private val startFailures by lazy { - SparseArrayCompat().apply { - for (field in WifiManager::class.java.declaredFields) try { - // all SAP_START_FAILURE_* are system-api since API 30 - if (field.name.startsWith("SAP_START_FAILURE_")) put(field.get(null) as Int, field.name) - } catch (e: Exception) { - Timber.w(e) - } - } - } - fun failureReason(reason: Int): String { - if (Build.VERSION.SDK_INT >= 30) try { - startFailures.get(reason)?.let { return it } - } catch (e: ReflectiveOperationException) { - Timber.w(e) - } - return startFailures29.getOrNull(reason) ?: app.getString(R.string.failure_reason_unknown, reason) - } + val failureReasonLookup = ConstantLookup("SAP_START_FAILURE_", + "SAP_START_FAILURE_GENERAL", "SAP_START_FAILURE_NO_CHANNEL") private val interfaceSoftApCallback by lazy { Class.forName("android.net.wifi.WifiManager\$SoftApCallback") } private val registerSoftApCallback by lazy { diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/util/ConstantLookup.kt b/mobile/src/main/java/be/mygod/vpnhotspot/util/ConstantLookup.kt new file mode 100644 index 00000000..032145a5 --- /dev/null +++ b/mobile/src/main/java/be/mygod/vpnhotspot/util/ConstantLookup.kt @@ -0,0 +1,33 @@ +package be.mygod.vpnhotspot.util + +import android.os.Build +import androidx.collection.SparseArrayCompat +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) { + private val lookup by lazy { + SparseArrayCompat().apply { + for (field in clazz.declaredFields) try { + if (field.name.startsWith(prefix)) put(field.get(null) as Int, field.name) + } catch (e: Exception) { + Timber.w(e) + } + } + } + operator fun invoke(reason: Int): String { + if (Build.VERSION.SDK_INT >= 30) try { + lookup.get(reason)?.let { return it } + } catch (e: ReflectiveOperationException) { + Timber.w(e) + } + return lookup29.getOrNull(reason) ?: app.getString(R.string.failure_reason_unknown, reason) + } +} + +@Suppress("FunctionName") +fun ConstantLookup(clazz: Class<*>, prefix: String, vararg lookup29: String) = ConstantLookup(clazz, prefix, lookup29) +@Suppress("FunctionName") +inline fun ConstantLookup(prefix: String, vararg lookup29: String) = + ConstantLookup(T::class.java, prefix, lookup29)