Listen for persistent group changes
This commit is contained in:
@@ -2,7 +2,6 @@ package be.mygod.vpnhotspot
|
|||||||
|
|
||||||
import android.app.Service
|
import android.app.Service
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.net.NetworkInfo
|
import android.net.NetworkInfo
|
||||||
import android.net.wifi.WpsInfo
|
import android.net.wifi.WpsInfo
|
||||||
@@ -58,6 +57,11 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
|
|||||||
val service get() = this@RepeaterService
|
val service get() = this@RepeaterService
|
||||||
val active get() = status == Status.ACTIVE
|
val active get() = status == Status.ACTIVE
|
||||||
val statusChanged = StickyEvent0()
|
val statusChanged = StickyEvent0()
|
||||||
|
var group: WifiP2pGroup? = null
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
groupChanged(value)
|
||||||
|
}
|
||||||
val groupChanged = StickyEvent1 { group }
|
val groupChanged = StickyEvent1 { group }
|
||||||
|
|
||||||
fun startWps(pin: String? = null) {
|
fun startWps(pin: String? = null) {
|
||||||
@@ -92,38 +96,10 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
|
|||||||
formatReason(R.string.repeater_reset_credentials_failure, reason)).show()
|
formatReason(R.string.repeater_reset_credentials_failure, reason)).show()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requestGroupUpdate() {
|
|
||||||
group = null
|
|
||||||
val channel = channel ?: return
|
|
||||||
val device = thisDevice ?: return
|
|
||||||
try {
|
|
||||||
p2pManager.requestPersistentGroupInfo(channel) {
|
|
||||||
val ownedGroups = it.filter { it.isGroupOwner && it.owner.deviceAddress == device.deviceAddress }
|
|
||||||
val main = ownedGroups.minBy { it.netId }
|
|
||||||
group = main
|
|
||||||
if (main != null) ownedGroups.filter { it.netId != main.netId }.forEach {
|
|
||||||
p2pManager.deletePersistentGroup(channel, it.netId, object : WifiP2pManager.ActionListener {
|
|
||||||
override fun onSuccess() = Timber.i("Removed redundant owned group: $it")
|
|
||||||
override fun onFailure(reason: Int) = SmartSnackbar.make(
|
|
||||||
formatReason(R.string.repeater_clean_pog_failure, reason)).show()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: ReflectiveOperationException) {
|
|
||||||
Timber.w(e)
|
|
||||||
SmartSnackbar.make(e).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val p2pManager get() = RepeaterService.p2pManager!!
|
private val p2pManager get() = RepeaterService.p2pManager!!
|
||||||
private var channel: WifiP2pManager.Channel? = null
|
private var channel: WifiP2pManager.Channel? = null
|
||||||
var group: WifiP2pGroup? = null
|
|
||||||
private set(value) {
|
|
||||||
field = value
|
|
||||||
binder.groupChanged(value)
|
|
||||||
}
|
|
||||||
private val binder = Binder()
|
private val binder = Binder()
|
||||||
private var receiverRegistered = false
|
private var receiverRegistered = false
|
||||||
private val receiver = broadcastReceiver { _, intent ->
|
private val receiver = broadcastReceiver { _, intent ->
|
||||||
@@ -140,9 +116,14 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
|
|||||||
private var routingManager: LocalOnlyInterfaceManager? = null
|
private var routingManager: LocalOnlyInterfaceManager? = null
|
||||||
|
|
||||||
private var thisDevice: WifiP2pDevice? = null
|
private var thisDevice: WifiP2pDevice? = null
|
||||||
private val thisDeviceListener = broadcastReceiver { _, intent ->
|
private val deviceListener = broadcastReceiver { _, intent ->
|
||||||
|
when (intent.action) {
|
||||||
|
WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION -> {
|
||||||
thisDevice = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE)
|
thisDevice = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE)
|
||||||
}
|
}
|
||||||
|
WifiP2pManagerHelper.WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION -> onPersistentGroupsChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var status = Status.IDLE
|
var status = Status.IDLE
|
||||||
private set(value) {
|
private set(value) {
|
||||||
@@ -164,8 +145,9 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
|
|||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
registerReceiver(thisDeviceListener, IntentFilter(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION))
|
|
||||||
onChannelDisconnected()
|
onChannelDisconnected()
|
||||||
|
registerReceiver(deviceListener, intentFilter(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION,
|
||||||
|
WifiP2pManagerHelper.WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION))
|
||||||
app.pref.registerOnSharedPreferenceChangeListener(this)
|
app.pref.registerOnSharedPreferenceChangeListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,7 +176,6 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
|
|||||||
if (status != Status.DESTROYED) try {
|
if (status != Status.DESTROYED) try {
|
||||||
channel = p2pManager.initialize(this, Looper.getMainLooper(), this)
|
channel = p2pManager.initialize(this, Looper.getMainLooper(), this)
|
||||||
setOperatingChannel()
|
setOperatingChannel()
|
||||||
binder.requestGroupUpdate()
|
|
||||||
} catch (e: RuntimeException) {
|
} catch (e: RuntimeException) {
|
||||||
Timber.w(e)
|
Timber.w(e)
|
||||||
app.handler.postDelayed(1000, this, this::onChannelDisconnected)
|
app.handler.postDelayed(1000, this, this::onChannelDisconnected)
|
||||||
@@ -205,6 +186,29 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
|
|||||||
if (key == App.KEY_OPERATING_CHANNEL) setOperatingChannel()
|
if (key == App.KEY_OPERATING_CHANNEL) setOperatingChannel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun onPersistentGroupsChanged() {
|
||||||
|
val channel = channel ?: return
|
||||||
|
val device = thisDevice ?: return
|
||||||
|
try {
|
||||||
|
p2pManager.requestPersistentGroupInfo(channel) {
|
||||||
|
val ownedGroups = it.filter { it.isGroupOwner && it.owner.deviceAddress == device.deviceAddress }
|
||||||
|
val main = ownedGroups.minBy { it.netId }
|
||||||
|
// do not replace current group if it's better
|
||||||
|
if (binder.group?.passphrase == null) binder.group = main
|
||||||
|
if (main != null) ownedGroups.filter { it.netId != main.netId }.forEach {
|
||||||
|
p2pManager.deletePersistentGroup(channel, it.netId, object : WifiP2pManager.ActionListener {
|
||||||
|
override fun onSuccess() = Timber.i("Removed redundant owned group: $it")
|
||||||
|
override fun onFailure(reason: Int) = SmartSnackbar.make(
|
||||||
|
formatReason(R.string.repeater_clean_pog_failure, reason)).show()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: ReflectiveOperationException) {
|
||||||
|
Timber.w(e)
|
||||||
|
SmartSnackbar.make(e).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* startService Step 1
|
* startService Step 1
|
||||||
*/
|
*/
|
||||||
@@ -248,7 +252,7 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
|
|||||||
if (routingManager != null) clean() // P2P shutdown, else other groups changing before start, ignore
|
if (routingManager != null) clean() // P2P shutdown, else other groups changing before start, ignore
|
||||||
}
|
}
|
||||||
routingManager != null -> {
|
routingManager != null -> {
|
||||||
this.group = group
|
binder.group = group
|
||||||
showNotification(group)
|
showNotification(group)
|
||||||
}
|
}
|
||||||
else -> doStart(group)
|
else -> doStart(group)
|
||||||
@@ -258,7 +262,7 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
|
|||||||
* startService Step 3
|
* startService Step 3
|
||||||
*/
|
*/
|
||||||
private fun doStart(group: WifiP2pGroup) {
|
private fun doStart(group: WifiP2pGroup) {
|
||||||
this.group = group
|
binder.group = group
|
||||||
check(routingManager == null)
|
check(routingManager == null)
|
||||||
routingManager = LocalOnlyInterfaceManager(group.`interface`!!)
|
routingManager = LocalOnlyInterfaceManager(group.`interface`!!)
|
||||||
status = Status.ACTIVE
|
status = Status.ACTIVE
|
||||||
@@ -304,9 +308,9 @@ class RepeaterService : Service(), WifiP2pManager.ChannelListener, SharedPrefere
|
|||||||
if (status != Status.IDLE) binder.shutdown()
|
if (status != Status.IDLE) binder.shutdown()
|
||||||
clean() // force clean to prevent leakage
|
clean() // force clean to prevent leakage
|
||||||
app.pref.unregisterOnSharedPreferenceChangeListener(this)
|
app.pref.unregisterOnSharedPreferenceChangeListener(this)
|
||||||
|
unregisterReceiver(deviceListener)
|
||||||
status = Status.DESTROYED
|
status = Status.DESTROYED
|
||||||
if (Build.VERSION.SDK_INT >= 27) channel?.close()
|
if (Build.VERSION.SDK_INT >= 27) channel?.close()
|
||||||
unregisterReceiver(thisDeviceListener)
|
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class RepeaterTileService : TileService(), ServiceConnection {
|
|||||||
binder.groupChanged -= this
|
binder.groupChanged -= this
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateTile(group: WifiP2pGroup? = binder?.service?.group) {
|
private fun updateTile(group: WifiP2pGroup? = binder?.group) {
|
||||||
val qsTile = qsTile ?: return
|
val qsTile = qsTile ?: return
|
||||||
when (binder?.service?.status) {
|
when (binder?.service?.status) {
|
||||||
RepeaterService.Status.IDLE -> {
|
RepeaterService.Status.IDLE -> {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class ClientViewModel : ViewModel(), ServiceConnection, IpNeighbourMonitor.Callb
|
|||||||
|
|
||||||
private fun populateClients() {
|
private fun populateClients() {
|
||||||
val clients = HashMap<Pair<String, String>, Client>()
|
val clients = HashMap<Pair<String, String>, Client>()
|
||||||
val group = repeater?.service?.group
|
val group = repeater?.group
|
||||||
val p2pInterface = group?.`interface`
|
val p2pInterface = group?.`interface`
|
||||||
if (p2pInterface != null) {
|
if (p2pInterface != null) {
|
||||||
for (client in p2p) clients[Pair(p2pInterface, client.deviceAddress)] = WifiP2pClient(p2pInterface, client)
|
for (client in p2p) clients[Pair(p2pInterface, client.deviceAddress)] = WifiP2pClient(p2pInterface, client)
|
||||||
@@ -50,7 +50,7 @@ class ClientViewModel : ViewModel(), ServiceConnection, IpNeighbourMonitor.Callb
|
|||||||
|
|
||||||
private fun refreshP2p() {
|
private fun refreshP2p() {
|
||||||
val repeater = repeater
|
val repeater = repeater
|
||||||
p2p = (if (repeater?.active != true) null else repeater.service.group?.clientList) ?: emptyList()
|
p2p = (if (repeater?.active != true) null else repeater.group?.clientList) ?: emptyList()
|
||||||
populateClients()
|
populateClients()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ class RepeaterManager(private val parent: TetheringFragment) : Manager(), Servic
|
|||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
val ssid @Bindable get() = binder?.service?.group?.networkName ?: ""
|
val ssid @Bindable get() = binder?.group?.networkName ?: ""
|
||||||
val addresses: CharSequence @Bindable get() {
|
val addresses: CharSequence @Bindable get() {
|
||||||
return try {
|
return try {
|
||||||
NetworkInterface.getByName(p2pInterface ?: return "")?.formatAddresses() ?: ""
|
NetworkInterface.getByName(p2pInterface ?: return "")?.formatAddresses() ?: ""
|
||||||
@@ -90,7 +90,7 @@ class RepeaterManager(private val parent: TetheringFragment) : Manager(), Servic
|
|||||||
|
|
||||||
fun editConfigurations() {
|
fun editConfigurations() {
|
||||||
val binder = binder
|
val binder = binder
|
||||||
val group = binder?.service?.group
|
val group = binder?.group
|
||||||
val ssid = group?.networkName
|
val ssid = group?.networkName
|
||||||
if (ssid != null) {
|
if (ssid != null) {
|
||||||
val wifi = WifiConfiguration()
|
val wifi = WifiConfiguration()
|
||||||
@@ -171,7 +171,7 @@ class RepeaterManager(private val parent: TetheringFragment) : Manager(), Servic
|
|||||||
DialogInterface.BUTTON_POSITIVE -> try {
|
DialogInterface.BUTTON_POSITIVE -> try {
|
||||||
data.getParcelableExtra<P2pSupplicantConfiguration>(WifiP2pDialogFragment.KEY_CONFIGURER)
|
data.getParcelableExtra<P2pSupplicantConfiguration>(WifiP2pDialogFragment.KEY_CONFIGURER)
|
||||||
.update(data.getParcelableExtra(WifiP2pDialogFragment.KEY_CONFIGURATION))
|
.update(data.getParcelableExtra(WifiP2pDialogFragment.KEY_CONFIGURATION))
|
||||||
app.handler.postDelayed(binder!!::requestGroupUpdate, 1000)
|
binder!!.group = null
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.w(e)
|
Timber.w(e)
|
||||||
SmartSnackbar.make(e).show()
|
SmartSnackbar.make(e).show()
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import java.lang.reflect.Proxy
|
|||||||
|
|
||||||
object WifiP2pManagerHelper {
|
object WifiP2pManagerHelper {
|
||||||
const val UNSUPPORTED = -2
|
const val UNSUPPORTED = -2
|
||||||
|
const val WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION = "android.net.wifi.p2p.PERSISTENT_GROUPS_CHANGED"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Available since Android 4.4.
|
* Available since Android 4.4.
|
||||||
|
|||||||
Reference in New Issue
Block a user