Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix p2p sync bugs #50

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,7 @@ interface DataSharingStrategy {

fun onPause()

fun onStop()

fun initChannel(onDeviceFound: OnDeviceFound, onConnected: DataSharingStrategy.PairingListener)
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,17 +101,19 @@ class WifiDirectDataSharingStrategy : DataSharingStrategy, P2PManagerListener {
requestAccessFineLocationIfNotGranted()
}

initChannel(onDeviceFound = onDeviceFound, onConnected = onConnected)
// Check if already connected and disconnect
disconnect(onDeviceFound = onDeviceFound, onConnected = onConnected)

listenForWifiP2pIntents()
initiatePeerDiscovery(onDeviceFound)
/* initChannel(onDeviceFound = onDeviceFound, onConnected = onConnected)
listenForWifiP2pEventsIntents()
initiatePeerDiscovery(onDeviceFound)*/
}

private fun requestConnectionInfo() {
wifiP2pManager.requestConnectionInfo(wifiP2pChannel) { onConnectionInfoAvailable(it, null) }
}

private fun listenForWifiP2pIntents() {
private fun listenForWifiP2pEventsIntents() {
wifiP2pReceiver?.also {
context.registerReceiver(
it,
Expand Down Expand Up @@ -186,6 +188,7 @@ class WifiDirectDataSharingStrategy : DataSharingStrategy, P2PManagerListener {
)
Timber.d("Peer discovery initiated")
}

private fun requestDeviceInfo() {
wifiP2pChannel?.also { wifiP2pChannel ->
if (ActivityCompat.checkSelfPermission(
Expand All @@ -207,6 +210,58 @@ class WifiDirectDataSharingStrategy : DataSharingStrategy, P2PManagerListener {
}
}
}

private fun disconnect(onDeviceFound: OnDeviceFound,
onConnected: DataSharingStrategy.PairingListener) {
wifiP2pChannel?.also { wifiP2pChannel ->
if (ActivityCompat.checkSelfPermission(
context,
android.Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
return handleAccessFineLocationNotGranted()
}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
wifiP2pManager.requestDeviceInfo(wifiP2pChannel) {
if (it != null && it.status == WifiP2pDevice.CONNECTED) {
disconnect(WifiDirectDevice(it), object: DataSharingStrategy.OperationListener {
override fun onSuccess(device: DeviceInfo?) {
Timber.e("Successfully disconnected from Wifi-Direct")
initChannel(onDeviceFound = onDeviceFound, onConnected = onConnected)
listenForWifiP2pEventsIntents()
initiatePeerDiscovery(onDeviceFound)
}

override fun onFailure(device: DeviceInfo?, ex: Exception) {
Timber.e(ex, "Failed to disconnect from Wifi-Direct")
}
})
}
}
} else {
wifiP2pManager.requestConnectionInfo(wifiP2pChannel) {
if (it != null && it.groupFormed) {
wifiP2pManager.removeGroup(
wifiP2pChannel,
object : WifiP2pManager.ActionListener {
override fun onSuccess() {
Timber.e("Successfully disconnected from Wifi-Direct")
initChannel(onDeviceFound = onDeviceFound, onConnected = onConnected)
listenForWifiP2pEventsIntents()
initiatePeerDiscovery(onDeviceFound)
}

override fun onFailure(reason: Int) {
Timber.e(Exception(getWifiP2pReason(reason)), "Failed to disconnect from Wifi-Direct")
}
})
}
}
}
}
}

override fun connect(
device: DeviceInfo,
operationListener: DataSharingStrategy.OperationListener
Expand Down Expand Up @@ -552,7 +607,7 @@ class WifiDirectDataSharingStrategy : DataSharingStrategy, P2PManagerListener {

override fun onResume(isScanning: Boolean) {
if (isScanning) {
listenForWifiP2pIntents()
listenForWifiP2pEventsIntents()
initiatePeerDiscoveryOnceAccessFineLocationGranted()
requestDeviceInfo()
requestConnectionInfo()
Expand Down Expand Up @@ -801,4 +856,24 @@ class WifiDirectDataSharingStrategy : DataSharingStrategy, P2PManagerListener {
return wifiP2pDevice.deviceAddress
}
}

override fun onStop() {
closeSocketAndStreams()

requestedDisconnection = true
wifiP2pManager.removeGroup(
wifiP2pChannel,
object : WifiP2pManager.ActionListener {
override fun onSuccess() {
Timber.i("Device successfully disconnected")
paired = false
}

override fun onFailure(reason: Int) {
val exception = Exception("Error #$reason: ${getWifiP2pReason(reason)}")
Timber.e(exception)
}
}
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,49 @@ import android.content.pm.PackageManager
import android.net.wifi.WifiManager
import android.os.Build
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.provider.Settings
import android.view.WindowManager
import android.widget.Button
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.app.ActivityCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.gms.common.api.ResolvableApiException
import com.google.android.gms.location.LocationRequest
import com.google.android.gms.location.LocationServices
import com.google.android.gms.location.LocationSettingsRequest
import com.google.android.gms.location.LocationSettingsResponse
import com.google.android.gms.tasks.OnFailureListener
import com.google.android.gms.tasks.OnSuccessListener
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.snackbar.Snackbar
import org.smartregister.p2p.P2PLibrary
import org.smartregister.p2p.R
import org.smartregister.p2p.authentication.model.DeviceRole
import org.smartregister.p2p.data_sharing.DataSharingStrategy
import org.smartregister.p2p.data_sharing.DeviceInfo
import org.smartregister.p2p.data_sharing.OnDeviceFound
import org.smartregister.p2p.model.P2PState
import org.smartregister.p2p.model.TransferProgress
import org.smartregister.p2p.search.adapter.DeviceListAdapter
import org.smartregister.p2p.search.contract.P2pModeSelectContract
import org.smartregister.p2p.search.ui.p2p.P2PScreen
import org.smartregister.p2p.search.ui.p2p.P2PViewModel
import org.smartregister.p2p.search.ui.theme.AppTheme
import org.smartregister.p2p.utils.DefaultDispatcherProvider
import org.smartregister.p2p.utils.getDeviceName
import org.smartregister.p2p.utils.isAppDebuggable
import org.smartregister.p2p.utils.startP2PScreen
import timber.log.Timber
Expand Down Expand Up @@ -347,4 +362,11 @@ class P2PDeviceSearchActivity : AppCompatActivity(), P2pModeSelectContract.View
}
}
}

override fun onStop() {
super.onStop()

//dataSharingStrategy.onStop()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -135,34 +135,46 @@ class WifiDirectDataSharingStrategyTest : RobolectricTest() {
}

@Test
fun `searchDevices() calls wifiP2pManager#initialize()`() {
fun `searchDevices() calls wifiDirectDataSharingStrategy#disconnect()`() {
every { context.checkPermission(any(), any(), any()) } returns PackageManager.PERMISSION_GRANTED
every { wifiP2pManager.initialize(context, context.mainLooper, null) } returns wifiP2pChannel
every { context.registerReceiver(any(), any()) } returns null
every { wifiP2pManager.discoverPeers(any(), any()) } just runs
every {
wifiDirectDataSharingStrategy invoke
"disconnect" withArguments
listOf(any<OnDeviceFound>(), any<DataSharingStrategy.PairingListener>())
} returns null

wifiDirectDataSharingStrategy.searchDevices(onDeviceFound, pairingListener)

verify { wifiP2pManager.initialize(context, context.mainLooper, null) }
verify {
wifiDirectDataSharingStrategy invoke
"disconnect" withArguments
listOf(onDeviceFound, pairingListener)
}

}

@Test
fun `searchDevices() initializes wifiP2pBroadcastReceiver`() {
fun `searchDevices() calls wifiDirectDataSharingStrategy#disconnect`() {
mockkConstructor(WifiP2pBroadcastReceiver::class)
every { context.checkPermission(any(), any(), any()) } returns PackageManager.PERMISSION_GRANTED
every { wifiP2pManager.initialize(context, context.mainLooper, null) } returns wifiP2pChannel
every { context.registerReceiver(any(), any()) } returns null
every { wifiP2pManager.discoverPeers(any(), any()) } just runs
every {
wifiDirectDataSharingStrategy invoke
"disconnect" withArguments
listOf(any<OnDeviceFound>(), any<DataSharingStrategy.PairingListener>())
} returns null

wifiDirectDataSharingStrategy.searchDevices(onDeviceFound, pairingListener)

val p2PManagerListenerSlot = slot<P2PManagerListener>()
verify {
constructedWith<WifiP2pBroadcastReceiver>(
EqMatcher(wifiP2pManager),
EqMatcher(wifiP2pChannel),
CapturingSlotMatcher(p2PManagerListenerSlot, P2PManagerListener::class),
EqMatcher(context)
)
wifiDirectDataSharingStrategy invoke
"disconnect" withArguments
listOf(onDeviceFound, pairingListener)
}
}

Expand All @@ -177,11 +189,11 @@ class WifiDirectDataSharingStrategyTest : RobolectricTest() {
}

@Test
fun `listenForWifiP2pIntents() calls context#registerReceiver() with correct intent filter actions`() {
fun `listenForWifiP2pEventsIntents() calls context#registerReceiver() with correct intent filter actions`() {
every { context.registerReceiver(any(), any()) } returns null
ReflectionHelpers.callInstanceMethod<WifiDirectDataSharingStrategy>(
wifiDirectDataSharingStrategy,
"listenForWifiP2pIntents"
"listenForWifiP2pEventsIntents"
)

val broadcastReceiverSlot = slot<BroadcastReceiver>()
Expand Down Expand Up @@ -805,8 +817,8 @@ class WifiDirectDataSharingStrategyTest : RobolectricTest() {
}

@Test
fun `onResume() calls listenForWifiP2pIntents(), initiatePeerDiscoveryOnceAccessFineLocationGranted(), requestDeviceInfo() and requestConnectionInfo() when isScanning is true`() {
every { wifiDirectDataSharingStrategy invokeNoArgs "listenForWifiP2pIntents" } returns null
fun `onResume() calls listenForWifiP2pEventsIntents(), initiatePeerDiscoveryOnceAccessFineLocationGranted(), requestDeviceInfo() and requestConnectionInfo() when isScanning is true`() {
every { wifiDirectDataSharingStrategy invokeNoArgs "listenForWifiP2pEventsIntents" } returns null
every {
wifiDirectDataSharingStrategy invokeNoArgs
"initiatePeerDiscoveryOnceAccessFineLocationGranted"
Expand All @@ -816,7 +828,7 @@ class WifiDirectDataSharingStrategyTest : RobolectricTest() {

wifiDirectDataSharingStrategy.onResume(isScanning = true)

verify { wifiDirectDataSharingStrategy invokeNoArgs "listenForWifiP2pIntents" }
verify { wifiDirectDataSharingStrategy invokeNoArgs "listenForWifiP2pEventsIntents" }
verify {
wifiDirectDataSharingStrategy invokeNoArgs
"initiatePeerDiscoveryOnceAccessFineLocationGranted"
Expand Down