From 006ecb894c6b7e35b244ee6fa235a911ce6c53c9 Mon Sep 17 00:00:00 2001 From: sim Date: Tue, 5 Sep 2023 21:50:17 +0200 Subject: [PATCH] Avoid concurrent (un)registration With synchronized MutableLists --- .../receivers/RegisterBroadcastReceiver.kt | 91 ++++++++++++------- 1 file changed, 57 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/org/unifiedpush/distributor/nextpush/receivers/RegisterBroadcastReceiver.kt b/app/src/main/java/org/unifiedpush/distributor/nextpush/receivers/RegisterBroadcastReceiver.kt index 1601805..beb519f 100644 --- a/app/src/main/java/org/unifiedpush/distributor/nextpush/receivers/RegisterBroadcastReceiver.kt +++ b/app/src/main/java/org/unifiedpush/distributor/nextpush/receivers/RegisterBroadcastReceiver.kt @@ -27,9 +27,6 @@ import kotlin.concurrent.schedule * THIS SERVICE IS USED BY OTHER APPS TO REGISTER */ -private val createQueue = emptyList().toMutableList() -private val delQueue = emptyList().toMutableList() - private const val WAKE_LOCK_TAG = "NextPush:RegisterBroadcastReceiver:lock" class RegisterBroadcastReceiver : BroadcastReceiver() { @@ -51,49 +48,53 @@ class RegisterBroadcastReceiver : BroadcastReceiver() { Log.w(TAG, "Trying to register an app without packageName") return } - when (checkToken(context, connectorToken, application)) { - TOKEN_REGISTERED_OK -> sendEndpoint(context, connectorToken) - TOKEN_NOK -> sendRegistrationFailed( - context, - application, - connectorToken - ) - TOKEN_NEW -> { - val appName = context.getApplicationName(application) ?: application - if (!isConnected(context)) { + if (!createQueue.containsTokenElseAdd(connectorToken)) { + when (checkToken(context, connectorToken, application)) { + TOKEN_REGISTERED_OK -> { + sendEndpoint(context, connectorToken) + createQueue.removeToken(connectorToken) + } + TOKEN_NOK -> { sendRegistrationFailed( context, application, - connectorToken, - message = "NextPush is not connected" + connectorToken ) - Toast.makeText( - context, - "Cannot register $appName, NextPush is not connected.", - Toast.LENGTH_SHORT - ).show() - return + createQueue.removeToken(connectorToken) } - if (connectorToken !in createQueue) { - createQueue.add(connectorToken) - delayRemove(createQueue, connectorToken) + TOKEN_NEW -> { + val appName = context.getApplicationName(application) ?: application + if (!isConnected(context)) { + sendRegistrationFailed( + context, + application, + connectorToken, + message = "NextPush is not connected" + ) + Toast.makeText( + context, + "Cannot register $appName, NextPush is not connected.", + Toast.LENGTH_SHORT + ).show() + return + } createApp( context, application, connectorToken ) { sendEndpoint(context, connectorToken) - createQueue.remove(connectorToken) + createQueue.removeToken(connectorToken) Toast.makeText( context, "$appName registered.", Toast.LENGTH_SHORT ).show() } - } else { - Log.d(TAG, "Already registering this token") } } + } else { + Log.d(TAG, "Already registering this token") } } ACTION_UNREGISTER -> { @@ -101,13 +102,11 @@ class RegisterBroadcastReceiver : BroadcastReceiver() { val connectorToken = intent.getStringExtra(EXTRA_TOKEN) ?: "" getDb(context).getPackageName(connectorToken) ?: return - if (connectorToken !in delQueue) { - delQueue.add(connectorToken) - delayRemove(delQueue, connectorToken) + if (!delQueue.containsTokenElseAdd(connectorToken)) { try { deleteApp(context, connectorToken) { Log.d(TAG, "Unregistration is finished") - delQueue.remove(connectorToken) + delQueue.removeToken(connectorToken) } } catch (e: Exception) { Log.d(TAG, "Could not delete app") @@ -124,9 +123,33 @@ class RegisterBroadcastReceiver : BroadcastReceiver() { } } - private fun delayRemove(list: MutableList, token: String) { - Timer().schedule(1_000L /* 1sec */) { - list.remove(token) + private fun MutableList.containsTokenElseAdd(connectorToken: String): Boolean { + return synchronized(this) { + if (connectorToken !in this) { + Log.d(TAG, "Token: $this") + this.add(connectorToken) + delayRemove(this, connectorToken) + false + } else { + true + } } } + + private fun MutableList.removeToken(connectorToken: String) { + synchronized(this) { + this.remove(connectorToken) + } + } + + private fun delayRemove(list: MutableList, token: String) { + Timer().schedule(1_000L /* 1sec */) { + list.removeToken(token) + } + } + + companion object { + private val createQueue = emptyList().toMutableList() + private val delQueue = emptyList().toMutableList() + } }