Check if Wi-Fi direct is available
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="be.mygod.vpnhotspot">
|
package="be.mygod.vpnhotspot">
|
||||||
|
|
||||||
|
<uses-feature android:name="android.hardware.wifi.direct" android:required="true"/>
|
||||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import android.util.Log
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import be.mygod.vpnhotspot.App.Companion.app
|
import be.mygod.vpnhotspot.App.Companion.app
|
||||||
import java.net.NetworkInterface
|
import java.net.NetworkInterface
|
||||||
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
class HotspotService : Service(), WifiP2pManager.ChannelListener {
|
class HotspotService : Service(), WifiP2pManager.ChannelListener {
|
||||||
companion object {
|
companion object {
|
||||||
@@ -24,6 +25,18 @@ class HotspotService : Service(), WifiP2pManager.ChannelListener {
|
|||||||
const val STATUS_CHANGED = "be.mygod.vpnhotspot.HotspotService.STATUS_CHANGED"
|
const val STATUS_CHANGED = "be.mygod.vpnhotspot.HotspotService.STATUS_CHANGED"
|
||||||
const val KEY_UPSTREAM = "service.upstream"
|
const val KEY_UPSTREAM = "service.upstream"
|
||||||
private const val TAG = "HotspotService"
|
private const val TAG = "HotspotService"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches the output of dumpsys wifip2p. This part is available since Android 4.2.
|
||||||
|
*
|
||||||
|
* Related sources:
|
||||||
|
* https://android.googlesource.com/platform/frameworks/base/+/f0afe4144d09aa9b980cffd444911ab118fa9cbe%5E%21/wifi/java/android/net/wifi/p2p/WifiP2pService.java
|
||||||
|
* https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/a8d5e40/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java#639
|
||||||
|
*
|
||||||
|
* https://android.googlesource.com/platform/frameworks/base.git/+/android-5.0.0_r1/core/java/android/net/NetworkInfo.java#433
|
||||||
|
* https://android.googlesource.com/platform/frameworks/base.git/+/220871a/core/java/android/net/NetworkInfo.java#415
|
||||||
|
*/
|
||||||
|
private val patternNetworkInfo = "^mNetworkInfo .* (isA|a)vailable: (true|false)".toPattern(Pattern.MULTILINE)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class Status {
|
enum class Status {
|
||||||
@@ -115,6 +128,15 @@ class HotspotService : Service(), WifiP2pManager.ChannelListener {
|
|||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
if (status != Status.IDLE) return START_NOT_STICKY
|
if (status != Status.IDLE) return START_NOT_STICKY
|
||||||
status = Status.STARTING
|
status = Status.STARTING
|
||||||
|
val matcher = patternNetworkInfo.matcher(loggerSu("dumpsys ${Context.WIFI_P2P_SERVICE}"))
|
||||||
|
if (!matcher.find()) {
|
||||||
|
startFailure("Root unavailable")
|
||||||
|
return START_NOT_STICKY
|
||||||
|
}
|
||||||
|
if (matcher.group(2) != "true") {
|
||||||
|
startFailure("Wi-Fi direct unavailable")
|
||||||
|
return START_NOT_STICKY
|
||||||
|
}
|
||||||
if (!receiverRegistered) {
|
if (!receiverRegistered) {
|
||||||
registerReceiver(receiver, intentFilter(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION,
|
registerReceiver(receiver, intentFilter(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION,
|
||||||
WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION))
|
WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION))
|
||||||
|
|||||||
@@ -24,18 +24,21 @@ fun Bundle.put(key: String, map: Array<String>): Bundle {
|
|||||||
|
|
||||||
const val NOISYSU_TAG = "NoisySU"
|
const val NOISYSU_TAG = "NoisySU"
|
||||||
const val NOISYSU_SUFFIX = "SUCCESS\n"
|
const val NOISYSU_SUFFIX = "SUCCESS\n"
|
||||||
fun noisySu(vararg commands: String): Boolean {
|
fun loggerSu(vararg commands: String): String {
|
||||||
val process = ProcessBuilder("su", "-c", """function noisy() { "$@" || echo "$@" exited with $?; }
|
val process = ProcessBuilder("su", "-c", commands.joinToString("\n"))
|
||||||
${commands.joinToString("\n") { if (it.startsWith("while ")) it else "noisy $it" }}
|
|
||||||
echo $NOISYSU_SUFFIX""")
|
|
||||||
.redirectErrorStream(true)
|
.redirectErrorStream(true)
|
||||||
.start()
|
.start()
|
||||||
process.waitFor()
|
process.waitFor()
|
||||||
var out = process.inputStream.bufferedReader().use { it.readLine() }
|
val err = process.errorStream.bufferedReader().use { it.readText() }
|
||||||
|
if (!err.isBlank()) Log.e(NOISYSU_TAG, err)
|
||||||
|
return process.inputStream.bufferedReader().use { it.readText() }
|
||||||
|
}
|
||||||
|
fun noisySu(vararg commands: String): Boolean {
|
||||||
|
var out = loggerSu("""function noisy() { "$@" || echo "$@" exited with $?; }
|
||||||
|
${commands.joinToString("\n") { if (it.startsWith("while ")) it else "noisy $it" }}
|
||||||
|
echo $NOISYSU_SUFFIX""")
|
||||||
val result = out != NOISYSU_SUFFIX
|
val result = out != NOISYSU_SUFFIX
|
||||||
out = out.removeSuffix(NOISYSU_SUFFIX)
|
out = out.removeSuffix(NOISYSU_SUFFIX)
|
||||||
if (!out.isNullOrBlank()) Log.i(NOISYSU_TAG, out)
|
if (!out.isBlank()) Log.i(NOISYSU_TAG, out)
|
||||||
val err = process.errorStream.bufferedReader().use { it.readLine() }
|
|
||||||
if (!err.isNullOrBlank()) Log.e(NOISYSU_TAG, err)
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user