NTP-4629 | Changed implementation to use mutex with suspend coroutine (#12792)

This commit is contained in:
Ujjwal Kumar
2024-09-26 19:03:20 +05:30
committed by GitHub
parent b06e58a3bd
commit 6aa47671d8

View File

@@ -8,15 +8,13 @@
package com.navi.pay.npcicl
import android.content.Context
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper.NAVI_UPI_NOT_RESET_CL_SERVICE_ON_DISCONNECT
import com.navi.pay.common.utils.NaviPayCommonUtils
import com.navi.pay.utils.NAVI_PAY_CL_INIT_RETRY_COUNT
import dagger.hilt.android.qualifiers.ApplicationContext
import java.util.concurrent.atomic.AtomicBoolean
import javax.inject.Inject
import javax.inject.Singleton
import kotlinx.coroutines.delay
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import org.npci.upi.security.services.CLServices
import org.npci.upi.security.services.ServiceConnectionStatusNotifier
@@ -26,72 +24,31 @@ class NpciClService @Inject constructor(@ApplicationContext private val context:
const val TAG = "NpciClService"
}
private var clService: CLServices? =
null // This is the limitation from NPCI side to make it static.
private val isServiceInitRunning = AtomicBoolean(false)
private val mutex = Mutex()
private var clService: CLServices? = null
init {
initService()
}
private fun initService() {
val naviPayAccessEligibility = NaviPayCommonUtils.getNaviPayAccessEligibility(context)
if (!naviPayAccessEligibility.isNaviPayAccessible) {
// User device doesn't meet the requirements to use UPI
return
}
if (isServiceInitRunning.get()) {
return
}
isServiceInitRunning.set(true)
if (clService != null) {
return
}
CLServices.initService(
context,
object : ServiceConnectionStatusNotifier {
override fun serviceConnected(clServices: CLServices) {
clService = clServices
isServiceInitRunning.set(false)
suspend fun instance(): CLServices {
mutex.withLock {
return suspendCoroutine { continuation ->
clService?.let {
continuation.resume(it)
return@suspendCoroutine
}
override fun serviceDisconnected() {
isServiceInitRunning.set(false)
if (
!FirebaseRemoteConfigHelper.getBoolean(
NAVI_UPI_NOT_RESET_CL_SERVICE_ON_DISCONNECT
)
) {
clService = null
CLServices.initService(
context,
object : ServiceConnectionStatusNotifier {
override fun serviceConnected(clServices: CLServices) {
clService = clServices
continuation.resume(clServices)
}
override fun serviceDisconnected() {
clService = null
}
}
}
)
}
)
}
suspend fun instance(retries: Int = 0): CLServices {
// Ensure initService() is called if clService is null
if (clService == null && !isServiceInitRunning.get()) {
initService()
}
// Check if CL service is already initialized
if (clService != null) {
return clService!!
}
// If maximum retries exceeded, throw an exception
if (retries >= NAVI_PAY_CL_INIT_RETRY_COUNT) {
throw NullPointerException(
"CL service is not initialized. Call initService() or check status of isServiceInitRunning before using it."
)
}
// If initialization is in progress, wait for it to complete
delay(timeMillis = 100)
// Retry with incremented count
return instance(retries = retries + 1)
}
}