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