From d6503ed78712bea4a8d1778fb52bba3d441769d3 Mon Sep 17 00:00:00 2001 From: Mygod Date: Wed, 27 May 2020 15:37:21 -0400 Subject: [PATCH] Add APIs to README --- README.md | 54 ++++++++++++------ .../mygod/vpnhotspot/net/TetheringManager.kt | 56 +++++++++++-------- 2 files changed, 68 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index e3d37a95..0c9b82e9 100644 --- a/README.md +++ b/README.md @@ -129,30 +129,54 @@ _a.k.a. things that can go wrong if this app doesn't work._ This is a list of stuff that might impact this app's functionality if unavailable. This is only meant to be an index. You can read more in the source code. -Non-public API list: +Greylisted APIs or internal constants: (some constants are hardcoded or implicitly used) * (since API 24) [`Landroid/bluetooth/BluetoothPan;->isTetheringOn()Z,greylist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#32103) -* (since API 24) [`Landroid/net/ConnectivityManager$OnStartTetheringCallback;->()V,system-api,whitelist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#123103) -* (since API 24) [`Landroid/net/ConnectivityManager$OnStartTetheringCallback;->onTetheringFailed()V,system-api,whitelist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#123104) -* (since API 24) [`Landroid/net/ConnectivityManager$OnStartTetheringCallback;->onTetheringStarted()V,system-api,whitelist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#123105) -* (since API 24) [`Landroid/net/ConnectivityManager;->getLastTetherError(Ljava/lang/String;)I,greylist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#123309) -* (since API 24) [`Landroid/net/ConnectivityManager;->startTethering(IZLandroid/net/ConnectivityManager$OnStartTetheringCallback;Landroid/os/Handler;)V,system-api,whitelist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#123408) -* (since API 24) [`Landroid/net/ConnectivityManager;->stopTethering(I)V,system-api,whitelist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#123410) -* (since API 30) `Landroid/net/TetheringManager;->TETHER_ERROR_*:I,system-api,test-api,whitelist` +* [`Landroid/net/ConnectivityManager;->getLastTetherError(Ljava/lang/String;)I,greylist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#123309) * (since API 23) [`Landroid/net/wifi/WifiConfiguration;->apBand:I,greylist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#131529) * (since API 23) [`Landroid/net/wifi/WifiConfiguration;->apChannel:I,greylist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#131530) * (since API 26) [`Landroid/net/wifi/WifiManager;->cancelLocalOnlyHotspotRequest()V,greylist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#132250) -* [`Landroid/net/wifi/WifiManager;->getWifiApConfiguration()Landroid/net/wifi/WifiConfiguration;,system-api,whitelist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#132289) -* [`Landroid/net/wifi/WifiManager;->setWifiApConfiguration(Landroid/net/wifi/WifiConfiguration;)Z,system-api,whitelist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#132358) -* (deprecated since API 26) `Landroid/net/wifi/WifiManager;->setWifiApEnabled(Landroid/net/wifi/WifiConfiguration;Z)Z` +* (prior to API 26) `Landroid/net/wifi/WifiManager;->setWifiApEnabled(Landroid/net/wifi/WifiConfiguration;Z)Z` * [`Landroid/net/wifi/p2p/WifiP2pGroup;->getNetworkId()I,greylist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#134440) * [`Landroid/net/wifi/p2p/WifiP2pGroupList;->getGroupList()Ljava/util/Collection;,greylist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#134487) +* [`Landroid/net/wifi/p2p/WifiP2pManager;->WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION:Ljava/lang/String;,greylist-max-o`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#134686) * [`Landroid/net/wifi/p2p/WifiP2pManager;->deletePersistentGroup(Landroid/net/wifi/p2p/WifiP2pManager$Channel;ILandroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V,greylist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#134703) * [`Landroid/net/wifi/p2p/WifiP2pManager;->requestPersistentGroupInfo(Landroid/net/wifi/p2p/WifiP2pManager$Channel;Landroid/net/wifi/p2p/WifiP2pManager$PersistentGroupInfoListener;)V,greylist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#134728) * [`Landroid/net/wifi/p2p/WifiP2pManager;->setWifiP2pChannels(Landroid/net/wifi/p2p/WifiP2pManager$Channel;IILandroid/net/wifi/p2p/WifiP2pManager$ActionListener;)V,greylist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#134737) * [`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/+/3d07e5c/appcompat/hiddenapi-flags.csv#134738) +* (since API 28) [`Landroid/provider/Settings$Global;->SOFT_AP_TIMEOUT_ENABLED:Ljava/lang/String;,greylist-max-o`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#158307) +* (since API 27) [`Landroid/provider/Settings$Global;->TETHER_OFFLOAD_DISABLED:Ljava/lang/String;,greylist-max-o`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#158331) +* (since API 27) `Lcom/android/server/connectivity/tethering/OffloadHardwareInterface;->DEFAULT_TETHER_OFFLOAD_DISABLED:I` * (prior to API 29) [`Ljava/net/InetAddress;->parseNumericAddress(Ljava/lang/String;)Ljava/net/InetAddress;,core-platform-api,greylist-max-p`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#335306) +Hidden whitelisted APIs: (same catch as above, however, things in this list are less likely to be broken) + +* (since API 30) `Landroid/content/Context;->TETHERING_SERVICE:Ljava/lang/String;,system-api,whitelist` +* (since API 24) [`Landroid/net/ConnectivityManager$OnStartTetheringCallback;->()V,system-api,whitelist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#123103) +* (since API 24) [`Landroid/net/ConnectivityManager$OnStartTetheringCallback;->onTetheringFailed()V,system-api,whitelist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#123104) +* (since API 24) [`Landroid/net/ConnectivityManager$OnStartTetheringCallback;->onTetheringStarted()V,system-api,whitelist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#123105) +* (since API 24) [`Landroid/net/ConnectivityManager;->startTethering(IZLandroid/net/ConnectivityManager$OnStartTetheringCallback;Landroid/os/Handler;)V,system-api,whitelist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#123408) +* (since API 24) [`Landroid/net/ConnectivityManager;->stopTethering(I)V,system-api,whitelist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#123410) +* (since API 30) `Landroid/net/TetheringManager$StartTetheringCallback;->onTetheringFailed(I)V,system-api,test-api,whitelist` +* (since API 30) `Landroid/net/TetheringManager$StartTetheringCallback;->onTetheringStarted()V,system-api,test-api,whitelist` +* (since API 30) `Landroid/net/TetheringManager$TetheringRequest$Builder;->(I)V,system-api,test-api,whitelist` +* (since API 30) `Landroid/net/TetheringManager$TetheringRequest$Builder;->build()Landroid/net/TetheringManager$TetheringRequest;,system-api,test-api,whitelist` +* (since API 30) `Landroid/net/TetheringManager$TetheringRequest$Builder;->setExemptFromEntitlementCheck(Z)Landroid/net/TetheringManager$TetheringRequest$Builder;,system-api,test-api,whitelist` +* (since API 30) `Landroid/net/TetheringManager$TetheringRequest$Builder;->setShouldShowEntitlementUi(Z)Landroid/net/TetheringManager$TetheringRequest$Builder;,system-api,test-api,whitelist` +* (since API 30) `Landroid/net/TetheringManager$TetheringRequest$Builder;->setStaticIpv4Addresses(Landroid/net/LinkAddress;Landroid/net/LinkAddress;)Landroid/net/TetheringManager$TetheringRequest$Builder;,system-api,test-api,whitelist` +* `Landroid/net/TetheringManager;->ACTION_TETHER_STATE_CHANGED:Ljava/lang/String;,system-api,test-api,whitelist` +* (since API 26) `Landroid/net/TetheringManager;->EXTRA_ACTIVE_LOCAL_ONLY:Ljava/lang/String;,system-api,test-api,whitelist` +* `Landroid/net/TetheringManager;->EXTRA_ACTIVE_TETHER:Ljava/lang/String;,system-api,test-api,whitelist` +* `Landroid/net/TetheringManager;->EXTRA_ERRORED_TETHER:Ljava/lang/String;,system-api,test-api,whitelist` +* (since API 24) `Landroid/net/TetheringManager;->TETHERING_BLUETOOTH:I,system-api,test-api,whitelist` +* (since API 24) `Landroid/net/TetheringManager;->TETHERING_USB:I,system-api,test-api,whitelist` +* (since API 24) `Landroid/net/TetheringManager;->TETHERING_WIFI:I,system-api,test-api,whitelist` +* `Landroid/net/TetheringManager;->TETHER_ERROR_*:I,system-api,test-api,whitelist` +* (since API 30) `Landroid/net/TetheringManager;->startTethering(Landroid/net/TetheringManager$TetheringRequest;Ljava/util/concurrent/Executor;Landroid/net/TetheringManager$StartTetheringCallback;)V,system-api,test-api,whitelist` +* (since API 30) `Landroid/net/TetheringManager;->stopTethering(I)V,system-api,test-api,whitelist` +* [`Landroid/net/wifi/WifiManager;->getWifiApConfiguration()Landroid/net/wifi/WifiConfiguration;,system-api,whitelist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#132289) +* [`Landroid/net/wifi/WifiManager;->setWifiApConfiguration(Landroid/net/wifi/WifiConfiguration;)Z,system-api,whitelist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#132358) + Undocumented system configurations: * `@android:array/config_tether_usb_regexs` @@ -164,13 +188,7 @@ Undocumented system configurations: Other: * (since API 29) `android.net.wifi.p2p.WifiP2pConfig` needs to be parcelized in a very specific order, except for possible extra fields at the end. (used only for safe mode) -* (since API 28) [`Landroid/provider/Settings$Global;->SOFT_AP_TIMEOUT_ENABLED:Ljava/lang/String;,greylist-max-o`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#158307) is assumed to be `"soft_ap_timeout_enabled"`. -* (since API 27) [`Landroid/provider/Settings$Global;->TETHER_OFFLOAD_DISABLED:Ljava/lang/String;,greylist-max-o`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#158331) is assumed to be `"tether_offload_disabled"`. -* (since API 27) `com.android.server.connectivity.tethering.OffloadHardwareInterface.DEFAULT_TETHER_OFFLOAD_DISABLED` is assumed to be 0. -* Several constants in `ConnectivityManager` is assumed to be defined as in `TetheringManager.kt`; -* Following broadcasts are assumed to be sticky: - - [`Landroid/net/ConnectivityManager;->ACTION_TETHER_STATE_CHANGED:Ljava/lang/String;,greylist`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#123163) is assumed to be `android.net.conn.TETHER_STATE_CHANGED`. - - [`Landroid/net/wifi/p2p/WifiP2pManager;->WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION:Ljava/lang/String;,greylist-max-o`](https://android.googlesource.com/platform/prebuilts/runtime/+/3d07e5c/appcompat/hiddenapi-flags.csv#134686) is assumed to be `android.net.wifi.p2p.PERSISTENT_GROUPS_CHANGED`; +* Broadcast `android.net.wifi.p2p.PERSISTENT_GROUPS_CHANGED` is assumed to be sticky. * Activity `com.android.settings/.Settings$TetherSettingsActivity` is assumed to be exported. For `ip rule` priorities, `RULE_PRIORITY_SECURE_VPN` and `RULE_PRIORITY_TETHERING` is assumed to be 12000 and 18000 respectively; 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 e1c6c2cf..5642830b 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/net/TetheringManager.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/net/TetheringManager.kt @@ -15,6 +15,7 @@ import com.android.dx.stock.ProxyBuilder import timber.log.Timber import java.lang.ref.WeakReference import java.lang.reflect.InvocationTargetException +import java.lang.reflect.Proxy import java.util.concurrent.Executor /** @@ -73,22 +74,32 @@ object TetheringManager { private const val EXTRA_ACTIVE_TETHER = "tetherArray" /** * gives a String[] listing all the interfaces we tried to tether and - * failed. Use {@link #getLastTetherError} to find the error code + * failed. Use [getLastTetherError] to find the error code * for any interfaces listed here. */ const val EXTRA_ERRORED_TETHER = "erroredArray" + /** + * Wifi tethering type. + * @see [startTethering]. + */ @RequiresApi(24) const val TETHERING_WIFI = 0 /** + * USB tethering type. + * * Requires MANAGE_USB permission, unfortunately. * * Source: https://android.googlesource.com/platform/frameworks/base/+/7ca5d3a/services/usb/java/com/android/server/usb/UsbService.java#389 + * @see [startTethering]. */ @RequiresApi(24) const val TETHERING_USB = 1 /** + * Bluetooth tethering type. + * * Requires BLUETOOTH permission, or BLUETOOTH_PRIVILEGED on API 30+. + * @see [startTethering]. */ @RequiresApi(24) const val TETHERING_BLUETOOTH = 2 @@ -111,7 +122,6 @@ object TetheringManager { private val stopTetheringLegacy by lazy { ConnectivityManager::class.java.getDeclaredMethod("stopTethering", Int::class.java) } - @get:RequiresApi(24) private val getLastTetherError by lazy { ConnectivityManager::class.java.getDeclaredMethod("getLastTetherError", String::class.java) } @@ -139,13 +149,13 @@ object TetheringManager { private val build by lazy { classTetheringRequestBuilder.getDeclaredMethod("build") } @get:RequiresApi(30) - private val classStartTetheringCallback by lazy { + private val interfaceStartTetheringCallback by lazy { Class.forName("android.net.TetheringManager\$StartTetheringCallback") } @get:RequiresApi(30) private val startTethering by lazy { clazz.getDeclaredMethod("startTethering", Class.forName("android.net.TetheringManager\$TetheringRequest"), - Executor::class.java, classStartTetheringCallback) + Executor::class.java, interfaceStartTetheringCallback) } @get:RequiresApi(30) private val stopTethering by lazy { clazz.getDeclaredMethod("stopTethering", Int::class.java) } @@ -194,28 +204,26 @@ object TetheringManager { build.invoke(this) } val executor = Executor { if (handler == null) it.run() else handler.post(it) } - val proxy = ProxyBuilder.forClass(classStartTetheringCallback).apply { - dexCache(app.deviceStorage.cacheDir) - handler { proxy, method, args -> - @Suppress("NAME_SHADOWING") val callback = reference.get() - when (val name = method.name) { - "onTetheringStarted" -> { - if (args.isNotEmpty()) Timber.w("Unexpected args for $name: $args") - callback?.onTetheringStarted() - null - } - "onTetheringFailed" -> { - if (args.size != 1) Timber.w("Unexpected args for $name: $args") - callback?.onTetheringFailed(args.getOrNull(0) as? Int?) - null - } - else -> { - Timber.w("Unexpected method, calling super: $method") - ProxyBuilder.callSuper(proxy, method, args) - } + val proxy = Proxy.newProxyInstance(interfaceStartTetheringCallback.classLoader, + arrayOf(interfaceStartTetheringCallback)) { proxy, method, args -> + @Suppress("NAME_SHADOWING") val callback = reference.get() + when (val name = method.name) { + "onTetheringStarted" -> { + if (args.isNotEmpty()) Timber.w("Unexpected args for $name: $args") + callback?.onTetheringStarted() + null + } + "onTetheringFailed" -> { + if (args.size != 1) Timber.w("Unexpected args for $name: $args") + callback?.onTetheringFailed(args.getOrNull(0) as? Int?) + null + } + else -> { + Timber.w("Unexpected method, calling super: $method") + ProxyBuilder.callSuper(proxy, method, args) } } - }.build() + } startTethering.invoke(instance, request, executor, proxy) return } catch (e: InvocationTargetException) {