From 7f41850a612bd39877d4476db484e30740c9747a Mon Sep 17 00:00:00 2001 From: Mygod Date: Fri, 10 May 2019 10:59:59 +0800 Subject: [PATCH 1/3] Prefer private API over private system configurations, deprecate WiMAX support --- README.md | 10 +--- .../be/mygod/vpnhotspot/net/TetherType.kt | 60 +++++-------------- 2 files changed, 18 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 5aef448c..77617536 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,9 @@ Undocumented API list: * (since API 24) [`Landroid/net/ConnectivityManager$OnStartTetheringCallback;->onTetheringFailed()V,whitelist`](https://android.googlesource.com/platform/prebuilts/runtime/+/aa21a6e/appcompat/hiddenapi-flags.csv#112696) * (since API 24) [`Landroid/net/ConnectivityManager$OnStartTetheringCallback;->onTetheringStarted()V,whitelist`](https://android.googlesource.com/platform/prebuilts/runtime/+/aa21a6e/appcompat/hiddenapi-flags.csv#112697) * (since API 24) [`Landroid/net/ConnectivityManager;->getLastTetherError(Ljava/lang/String;)I,greylist`](https://android.googlesource.com/platform/prebuilts/runtime/+/aa21a6e/appcompat/hiddenapi-flags.csv#112882) +* [`Landroid/net/ConnectivityManager;->getTetherableBluetoothRegexs()[Ljava/lang/String;,greylist`](https://android.googlesource.com/platform/prebuilts/runtime/+/aa21a6e/appcompat/hiddenapi-flags.csv#112901) +* [`Landroid/net/ConnectivityManager;->getTetherableUsbRegexs()[Ljava/lang/String;,greylist`](https://android.googlesource.com/platform/prebuilts/runtime/+/aa21a6e/appcompat/hiddenapi-flags.csv#112903) +* [`Landroid/net/ConnectivityManager;->getTetherableWifiRegexs()[Ljava/lang/String;,greylist`](https://android.googlesource.com/platform/prebuilts/runtime/+/aa21a6e/appcompat/hiddenapi-flags.csv#112904) * (since API 24) [`Landroid/net/ConnectivityManager;->startTethering(IZLandroid/net/ConnectivityManager$OnStartTetheringCallback;Landroid/os/Handler;)V,whitelist`](https://android.googlesource.com/platform/prebuilts/runtime/+/aa21a6e/appcompat/hiddenapi-flags.csv#112972) * (since API 24) [`Landroid/net/ConnectivityManager;->stopTethering(I)V,whitelist`](https://android.googlesource.com/platform/prebuilts/runtime/+/aa21a6e/appcompat/hiddenapi-flags.csv#112974) * (since API 23) [`Landroid/net/wifi/WifiConfiguration;->apBand:I,greylist`](https://android.googlesource.com/platform/prebuilts/runtime/+/aa21a6e/appcompat/hiddenapi-flags.csv#120723) @@ -129,13 +132,6 @@ Undocumented API list: * [`Landroid/net/wifi/p2p/WifiP2pManager;->startWps(Landroid/net/wifi/p2p/WifiP2pManager$Channel;Landroid/net/wifi/WpsInfo;Landroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V,greylist`](https://android.googlesource.com/platform/prebuilts/runtime/+/aa21a6e/appcompat/hiddenapi-flags.csv#123459) * [`Ljava/net/InetAddress;->parseNumericAddress(Ljava/lang/String;)Ljava/net/InetAddress;,greylist`](https://android.googlesource.com/platform/prebuilts/runtime/+/aa21a6e/appcompat/hiddenapi-flags.csv#299587) -Undocumented system configurations: - -* `@android:array/config_tether_usb_regexs` -* `@android:array/config_tether_wifi_regexs` -* `@android:array/config_tether_wimax_regexs` -* `@android:array/config_tether_bluetooth_regexs` - Other: * (since API 27) [`Landroid/provider/Settings$Global;->TETHER_OFFLOAD_DISABLED:Ljava/lang/String;,greylist-max-o`](https://android.googlesource.com/platform/prebuilts/runtime/+/aa21a6e/appcompat/hiddenapi-flags.csv#144760) is assumed to be `"tether_offload_disabled"`. diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/net/TetherType.kt b/mobile/src/main/java/be/mygod/vpnhotspot/net/TetherType.kt index 00673aaf..070106f4 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/net/TetherType.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/net/TetherType.kt @@ -1,54 +1,25 @@ package be.mygod.vpnhotspot.net -import android.content.res.Resources +import android.net.ConnectivityManager import be.mygod.vpnhotspot.App.Companion.app import be.mygod.vpnhotspot.R -import java.util.regex.Pattern -enum class TetherType { - NONE, WIFI_P2P, USB, WIFI, WIMAX, BLUETOOTH; - - val icon get() = when (this) { - USB -> R.drawable.ic_device_usb - WIFI_P2P -> R.drawable.ic_action_settings_input_antenna - WIFI, WIMAX -> R.drawable.ic_device_network_wifi - BLUETOOTH -> R.drawable.ic_device_bluetooth - else -> R.drawable.ic_device_wifi_tethering - } - val isWifi get() = when (this) { - WIFI_P2P, WIFI, WIMAX -> true - else -> false - } +enum class TetherType(val icon: Int, val isWifi: Boolean = false) { + NONE(R.drawable.ic_device_wifi_tethering), + WIFI_P2P(R.drawable.ic_action_settings_input_antenna, true), + USB(R.drawable.ic_device_usb), + WIFI(R.drawable.ic_device_network_wifi, true), + BLUETOOTH(R.drawable.ic_device_bluetooth); companion object { - private val usbRegexs: List - private val wifiRegexs: List - private val wimaxRegexs: List - private val bluetoothRegexs: List - - /** - * Source: https://android.googlesource.com/platform/frameworks/base/+/61fa313/core/res/res/values/config.xml#328 - */ - init { - val appRes = app.resources - val sysRes = Resources.getSystem() - usbRegexs = appRes.getStringArray(sysRes - .getIdentifier("config_tether_usb_regexs", "array", "android")) - .filterNotNull() - .map { it.toPattern() } - wifiRegexs = appRes.getStringArray(sysRes - .getIdentifier("config_tether_wifi_regexs", "array", "android")) - .filterNotNull() - .map { it.toPattern() } - wimaxRegexs = appRes.getStringArray(sysRes - .getIdentifier("config_tether_wimax_regexs", "array", "android")) - .filterNotNull() - .map { it.toPattern() } - bluetoothRegexs = appRes.getStringArray(sysRes - .getIdentifier("config_tether_bluetooth_regexs", "array", "android")) - .filterNotNull() - .map { it.toPattern() } - } + private fun getRegexs(type: String) = + (ConnectivityManager::class.java.getDeclaredMethod("getTetherable${type}Regexs") + .invoke(app.connectivity) as Array) + .filterNotNull() + .map { it.toPattern() } + private val usbRegexs = getRegexs("Usb") + private val wifiRegexs = getRegexs("Wifi") + private val bluetoothRegexs = getRegexs("Bluetooth") /** * Based on: https://android.googlesource.com/platform/frameworks/base/+/0e3d092/services/core/java/com/android/server/connectivity/Tethering.java#311 @@ -59,7 +30,6 @@ enum class TetherType { wifiRegexs.any { it.matcher(iface).matches() } -> WIFI usbRegexs.any { it.matcher(iface).matches() } -> USB bluetoothRegexs.any { it.matcher(iface).matches() } -> BLUETOOTH - wimaxRegexs.any { it.matcher(iface).matches() } -> WIMAX else -> NONE } } From cb589560f7698456914e625f3883a7019cb984cf Mon Sep 17 00:00:00 2001 From: Mygod Date: Fri, 10 May 2019 11:27:34 +0800 Subject: [PATCH 2/3] Disable tethering QS tiles if receiver does not work Also fixes a memory leak. --- .../manage/TetherListeningTileService.kt | 7 ++- .../vpnhotspot/manage/TetheringTileService.kt | 55 ++++++++++++------- 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetherListeningTileService.kt b/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetherListeningTileService.kt index 0917b7e0..896211b0 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetherListeningTileService.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetherListeningTileService.kt @@ -9,7 +9,7 @@ import be.mygod.vpnhotspot.util.broadcastReceiver @RequiresApi(24) abstract class TetherListeningTileService : KillableTileService() { - protected var tethered: List = emptyList() + protected var tethered: List? = null private val receiver = broadcastReceiver { _, intent -> tethered = intent.tetheredIfaces @@ -18,8 +18,9 @@ abstract class TetherListeningTileService : KillableTileService() { override fun onStartListening() { super.onStartListening() - val intent = registerReceiver(receiver, IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED)) - if (intent != null) tethered = intent.tetheredIfaces + tethered = registerReceiver(receiver, IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED)) + ?.tetheredIfaces + updateTile() } override fun onStopListening() { 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 143cea53..4fa87258 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetheringTileService.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetheringTileService.kt @@ -29,7 +29,7 @@ sealed class TetheringTileService : TetherListeningTileService(), TetheringManag protected abstract val labelString: Int protected abstract val tetherType: TetherType protected open val icon get() = tetherType.icon - protected val interested get() = tethered.filter { TetherType.ofInterface(it) == tetherType } + protected val interested get() = tethered?.filter { TetherType.ofInterface(it) == tetherType } protected var binder: TetheringService.Binder? = null protected abstract fun start() @@ -52,19 +52,27 @@ sealed class TetheringTileService : TetherListeningTileService(), TetheringManag } override fun onServiceDisconnected(name: ComponentName?) { + binder?.routingsChanged?.remove(this) binder = null } override fun updateTile() { qsTile?.run { val interested = interested - if (interested.isEmpty()) { - state = Tile.STATE_INACTIVE - icon = tileOff - } else { - val binder = binder ?: return - state = Tile.STATE_ACTIVE - icon = if (interested.all(binder::isActive)) tileOn else tileOff + when { + interested == null -> { + state = Tile.STATE_UNAVAILABLE + icon = tileOff + } + interested.isEmpty() -> { + state = Tile.STATE_INACTIVE + icon = tileOff + } + else -> { + val binder = binder ?: return + state = Tile.STATE_ACTIVE + icon = if (interested.all(binder::isActive)) tileOn else tileOff + } } label = getText(labelString) updateTile() @@ -88,7 +96,7 @@ sealed class TetheringTileService : TetherListeningTileService(), TetheringManag } } override fun onClick() { - val interested = interested + val interested = interested ?: return if (interested.isEmpty()) safeInvoker { start() } else { val binder = binder if (binder == null) tapPending = true else { @@ -146,11 +154,14 @@ sealed class TetheringTileService : TetherListeningTileService(), TetheringManag override fun updateTile() { qsTile?.run { - when (tethering?.active) { + val interested = interested + if (interested == null) { + state = Tile.STATE_UNAVAILABLE + icon = tileOff + } else when (tethering?.active) { true -> { val binder = binder ?: return state = Tile.STATE_ACTIVE - val interested = interested icon = if (interested.isNotEmpty() && interested.all(binder::isActive)) tileOn else tileOff } false -> { @@ -164,18 +175,20 @@ sealed class TetheringTileService : TetherListeningTileService(), TetheringManag } } - override fun onClick() = when (tethering?.active) { - true -> { - val binder = binder - if (binder == null) tapPending = true else { - val inactive = interested.filterNot(binder::isActive) - if (inactive.isEmpty()) safeInvoker { stop() } - else ContextCompat.startForegroundService(this, Intent(this, TetheringService::class.java) - .putExtra(TetheringService.EXTRA_ADD_INTERFACES, inactive.toTypedArray())) + override fun onClick() { + when (tethering?.active) { + true -> { + val binder = binder + if (binder == null) tapPending = true else { + val inactive = (interested ?: return).filterNot(binder::isActive) + if (inactive.isEmpty()) safeInvoker { stop() } + else ContextCompat.startForegroundService(this, Intent(this, TetheringService::class.java) + .putExtra(TetheringService.EXTRA_ADD_INTERFACES, inactive.toTypedArray())) + } } + false -> safeInvoker { start() } + else -> tapPending = true } - false -> safeInvoker { start() } - else -> tapPending = true } } From 7a3abdc429a71551ffd5bd55d54bdf80ceb29c75 Mon Sep 17 00:00:00 2001 From: Mygod Date: Fri, 10 May 2019 12:43:35 +0800 Subject: [PATCH 3/3] 2.4.2 --- mobile/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mobile/build.gradle b/mobile/build.gradle index 839bbaea..8f782286 100644 --- a/mobile/build.gradle +++ b/mobile/build.gradle @@ -20,8 +20,8 @@ android { minSdkVersion 21 targetSdkVersion 28 resConfigs "ru", "zh-rCN" - versionCode 201 - versionName "2.4.1" + versionCode 202 + versionName "2.4.2" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" javaCompileOptions { annotationProcessorOptions {