diff --git a/java/arcs/sdk/android/storage/service/DatabaseGarbageCollectionPeriodicTaskV2.kt b/java/arcs/sdk/android/storage/service/DatabaseGarbageCollectionPeriodicTaskV2.kt index 8eb1ae496f3..1ab4d1d3efc 100644 --- a/java/arcs/sdk/android/storage/service/DatabaseGarbageCollectionPeriodicTaskV2.kt +++ b/java/arcs/sdk/android/storage/service/DatabaseGarbageCollectionPeriodicTaskV2.kt @@ -48,7 +48,7 @@ class DatabaseGarbageCollectionPeriodicTaskV2( // work on any important threads that you're using elsewhere. override fun doWork(): Result = runBlocking { log.debug { "Running." } - val success = StorageServiceManagerEndpoint( + val success = StorageServiceManagerEndpointImpl( binderHelper, this, storageServiceClass.java diff --git a/java/arcs/sdk/android/storage/service/StorageServiceManagerEndpoint.kt b/java/arcs/sdk/android/storage/service/StorageServiceManagerEndpoint.kt index bf67e094d51..21c7e7bfccf 100644 --- a/java/arcs/sdk/android/storage/service/StorageServiceManagerEndpoint.kt +++ b/java/arcs/sdk/android/storage/service/StorageServiceManagerEndpoint.kt @@ -1,95 +1,32 @@ package arcs.sdk.android.storage.service -import arcs.android.storage.service.IHardReferencesRemovalCallback -import arcs.android.storage.service.IResultCallback -import arcs.android.storage.service.IStorageServiceManager import arcs.android.storage.service.StorageServiceManager -import arcs.android.storage.service.suspendForHardReferencesCallback -import arcs.android.storage.service.suspendForResultCallback import arcs.core.data.Schema -import arcs.core.storage.keys.ForeignStorageKey -import kotlinx.coroutines.CoroutineScope /** * A [StorageServiceManagerEndpoint] can be used to bind to an Android [StorageServiceManager] and * call its callback-style methods. */ -class StorageServiceManagerEndpoint( - private val bindHelper: BindHelper, - private val scope: CoroutineScope, - private val storageServiceClass: Class<*> = StorageService::class.java -) { +interface StorageServiceManagerEndpoint { /** - * Triggers a hard reference deletions for foreign hard references with the given Schema namespace - * and ID. + * Triggers a hard reference deletions for foreign hard references with the given Schema [namespace] + * and [id]. + * + * @return the number of entities removed. */ - suspend fun triggerForeignHardReferenceDeletion(namespace: Schema, id: String): Long { - return runOnStorageServiceManager { manager, result -> - manager.triggerHardReferenceDeletion(stringForeignStorageKey(namespace), id, result) - } - } + suspend fun triggerForeignHardReferenceDeletion(namespace: Schema, id: String): Long /** * Triggers a hard reference reconciliation for foreign hard references with the given Schema - * namespace and ID. + * [namespace] and [id]. + * + * @return the number of entities removed. */ - suspend fun reconcileForeignHardReference(namespace: Schema, idsToRetain: Set): Long { - return runOnStorageServiceManager { manager, result -> - manager.reconcileHardReferences( - stringForeignStorageKey(namespace), - idsToRetain.toList(), - result - ) - } - } + suspend fun reconcileForeignHardReference(namespace: Schema, idsToRetain: Set): Long /** * Binds to the IStorageServiceManager and starts a garbage collection run. */ - suspend fun runGarbageCollection(): Boolean { - return runIResultCallbackOnStorageServiceManager { manager, callback -> - manager.runGarbageCollection(callback) - } - } - - /** - * Binds to the IStorageServiceManager, and runs the given block on it. It can be used to run one - * of the methods that take a [IResultCallback]. - */ - private suspend fun runIResultCallbackOnStorageServiceManager( - block: (IStorageServiceManager, IResultCallback) -> Unit - ): Boolean { - return withBoundService { - suspendForResultCallback { resultCallback -> - block(it, resultCallback) - } - } - } - - private suspend fun runOnStorageServiceManager( - block: (IStorageServiceManager, IHardReferencesRemovalCallback) -> Unit - ): Long { - return withBoundService { - suspendForHardReferencesCallback { resultCallback -> - block(it, resultCallback) - } - } - } - - private suspend fun withBoundService(block: suspend (IStorageServiceManager) -> T): T { - val intent = StorageServiceIntentHelpers.managerIntent(bindHelper.context, storageServiceClass) - val boundService = bindHelper.bindForIntent( - intent, - scope, - IStorageServiceManager.Stub::asInterface - ) - try { - return block(boundService.service) - } finally { - boundService.disconnect() - } - } - - private fun stringForeignStorageKey(namespace: Schema) = ForeignStorageKey(namespace).toString() + suspend fun runGarbageCollection() } diff --git a/java/arcs/sdk/android/storage/service/StorageServiceManagerEndpointImpl.kt b/java/arcs/sdk/android/storage/service/StorageServiceManagerEndpointImpl.kt new file mode 100644 index 00000000000..c18738c0a86 --- /dev/null +++ b/java/arcs/sdk/android/storage/service/StorageServiceManagerEndpointImpl.kt @@ -0,0 +1,87 @@ +package arcs.sdk.android.storage.service + +import arcs.android.storage.service.IHardReferencesRemovalCallback +import arcs.android.storage.service.IResultCallback +import arcs.android.storage.service.IStorageServiceManager +import arcs.android.storage.service.StorageServiceManager +import arcs.android.storage.service.suspendForHardReferencesCallback +import arcs.android.storage.service.suspendForResultCallback +import arcs.core.data.Schema +import arcs.core.storage.keys.ForeignStorageKey +import kotlinx.coroutines.CoroutineScope + +/** + * Implementation of [StorageServiceManagerEndpoint] that binds to an Android [StorageServiceManager] and + * call its callback-style methods. + */ +class StorageServiceManagerEndpointImpl( + private val bindHelper: BindHelper, + private val scope: CoroutineScope, + private val storageServiceClass: Class<*> = StorageService::class.java +) : StorageServiceManagerEndpoint { + + override suspend fun triggerForeignHardReferenceDeletion(namespace: Schema, id: String): Long { + return runOnStorageServiceManager { manager, result -> + manager.triggerHardReferenceDeletion(stringForeignStorageKey(namespace), id, result) + } + } + + override suspend fun reconcileForeignHardReference( + namespace: Schema, + idsToRetain: Set + ): Long { + return runOnStorageServiceManager { manager, result -> + manager.reconcileHardReferences( + stringForeignStorageKey(namespace), + idsToRetain.toList(), + result + ) + } + } + + override suspend fun runGarbageCollection() { + runIResultCallbackOnStorageServiceManager { manager, callback -> + manager.runGarbageCollection(callback) + } + } + + /** + * Binds to the IStorageServiceManager, and runs the given block on it. It can be used to run one + * of the methods that take a [IResultCallback]. + */ + private suspend fun runIResultCallbackOnStorageServiceManager( + block: (IStorageServiceManager, IResultCallback) -> Unit + ): Boolean { + return withBoundService { + suspendForResultCallback { resultCallback -> + block(it, resultCallback) + } + } + } + + private suspend fun runOnStorageServiceManager( + block: (IStorageServiceManager, IHardReferencesRemovalCallback) -> Unit + ): Long { + return withBoundService { + suspendForHardReferencesCallback { resultCallback -> + block(it, resultCallback) + } + } + } + + private suspend fun withBoundService(block: suspend (IStorageServiceManager) -> T): T { + val intent = StorageServiceIntentHelpers.managerIntent(bindHelper.context, storageServiceClass) + val boundService = bindHelper.bindForIntent( + intent, + scope, + IStorageServiceManager.Stub::asInterface + ) + try { + return block(boundService.service) + } finally { + boundService.disconnect() + } + } + + private fun stringForeignStorageKey(namespace: Schema) = ForeignStorageKey(namespace).toString() +} diff --git a/javatests/arcs/android/integration/IntegrationEnvironment.kt b/javatests/arcs/android/integration/IntegrationEnvironment.kt index 88ea60fe8c0..e86165aeb72 100644 --- a/javatests/arcs/android/integration/IntegrationEnvironment.kt +++ b/javatests/arcs/android/integration/IntegrationEnvironment.kt @@ -33,7 +33,7 @@ import arcs.sdk.android.storage.AndroidStorageServiceEndpointManager import arcs.sdk.android.storage.service.DatabaseGarbageCollectionPeriodicTaskV2 import arcs.sdk.android.storage.service.StorageService import arcs.sdk.android.storage.service.StorageService.StorageServiceConfig -import arcs.sdk.android.storage.service.StorageServiceManagerEndpoint +import arcs.sdk.android.storage.service.StorageServiceManagerEndpointImpl import arcs.sdk.android.storage.service.testutil.TestBindHelper import arcs.sdk.android.storage.service.testutil.TestWorkerFactory import kotlin.coroutines.CoroutineContext @@ -322,14 +322,14 @@ class IntegrationEnvironment( } suspend fun triggerHardReferenceDelete(namespace: Schema, id: String): Long { - return StorageServiceManagerEndpoint( + return StorageServiceManagerEndpointImpl( TestBindHelper(ApplicationProvider.getApplicationContext()), testScope ).triggerForeignHardReferenceDeletion(namespace, id) } suspend fun reconcileHardReference(namespace: Schema, fullSet: Set): Long { - return StorageServiceManagerEndpoint( + return StorageServiceManagerEndpointImpl( TestBindHelper(ApplicationProvider.getApplicationContext()), testScope ).reconcileForeignHardReference(namespace, fullSet) diff --git a/javatests/arcs/sdk/android/storage/service/StorageServiceManagerEndpointTest.kt b/javatests/arcs/sdk/android/storage/service/StorageServiceManagerEndpointImplTest.kt similarity index 87% rename from javatests/arcs/sdk/android/storage/service/StorageServiceManagerEndpointTest.kt rename to javatests/arcs/sdk/android/storage/service/StorageServiceManagerEndpointImplTest.kt index 620482e73f2..7de217936dd 100644 --- a/javatests/arcs/sdk/android/storage/service/StorageServiceManagerEndpointTest.kt +++ b/javatests/arcs/sdk/android/storage/service/StorageServiceManagerEndpointImplTest.kt @@ -23,7 +23,7 @@ import org.junit.runner.RunWith @OptIn(ExperimentalCoroutinesApi::class) @RunWith(AndroidJUnit4::class) -class StorageServiceManagerEndpointTest { +class StorageServiceManagerEndpointImplTest { private lateinit var app: Application private val SCHEMA_NAME = "name" @@ -53,7 +53,7 @@ class StorageServiceManagerEndpointTest { @Test fun triggerForeignHardReferenceDeletion_propagatesToDatabase() = runBlocking { val testBindHelper = TestBindHelper(app) - val endpoint = StorageServiceManagerEndpoint(testBindHelper, this@runBlocking) + val endpoint = StorageServiceManagerEndpointImpl(testBindHelper, this@runBlocking) endpoint.triggerForeignHardReferenceDeletion(schema, "id") @@ -66,7 +66,7 @@ class StorageServiceManagerEndpointTest { @Test fun triggerForeignHardReferenceDeletion_sequenceOfCalls() = runBlocking { val testBindHelper = TestBindHelper(app) - val endpoint = StorageServiceManagerEndpoint(testBindHelper, this@runBlocking) + val endpoint = StorageServiceManagerEndpointImpl(testBindHelper, this@runBlocking) assertThat(database.hardReferenceDeletes).isEmpty() endpoint.triggerForeignHardReferenceDeletion(schema, "id") @@ -86,7 +86,7 @@ class StorageServiceManagerEndpointTest { @Test fun reconcileForeignHardReference_deletesOne() = runBlocking { val testBindHelper = TestBindHelper(app) - val endpoint = StorageServiceManagerEndpoint(testBindHelper, this@runBlocking) + val endpoint = StorageServiceManagerEndpointImpl(testBindHelper, this@runBlocking) database.allHardReferenceIds.add("id1") endpoint.reconcileForeignHardReference(schema, setOf("id2")) @@ -100,7 +100,7 @@ class StorageServiceManagerEndpointTest { @Test fun reconcileForeignHardReference_partialOvelap() = runBlocking { val testBindHelper = TestBindHelper(app) - val endpoint = StorageServiceManagerEndpoint(testBindHelper, this@runBlocking) + val endpoint = StorageServiceManagerEndpointImpl(testBindHelper, this@runBlocking) database.allHardReferenceIds.addAll(listOf("id1", "id2")) endpoint.reconcileForeignHardReference(schema, setOf("id2")) @@ -114,7 +114,7 @@ class StorageServiceManagerEndpointTest { @Test fun reconcileForeignHardReference_deletesNone() = runBlocking { val testBindHelper = TestBindHelper(app) - val endpoint = StorageServiceManagerEndpoint(testBindHelper, this@runBlocking) + val endpoint = StorageServiceManagerEndpointImpl(testBindHelper, this@runBlocking) database.allHardReferenceIds.add("id1") endpoint.reconcileForeignHardReference(schema, setOf("id1")) @@ -126,7 +126,7 @@ class StorageServiceManagerEndpointTest { @Test fun reconcileForeignHardReference_emptyValidSet() = runBlocking { val testBindHelper = TestBindHelper(app) - val endpoint = StorageServiceManagerEndpoint(testBindHelper, this@runBlocking) + val endpoint = StorageServiceManagerEndpointImpl(testBindHelper, this@runBlocking) database.allHardReferenceIds.add("id1") endpoint.reconcileForeignHardReference(schema, emptySet()) @@ -143,7 +143,7 @@ class StorageServiceManagerEndpointTest { val databaseManager = FakeDatabaseManager { dbManagerGcCalled = true } DriverAndKeyConfigurator.configure(databaseManager) val testBindHelper = TestBindHelper(app) - val endpoint = StorageServiceManagerEndpoint(testBindHelper, this@runBlocking) + val endpoint = StorageServiceManagerEndpointImpl(testBindHelper, this@runBlocking) endpoint.runGarbageCollection() @@ -158,7 +158,7 @@ class StorageServiceManagerEndpointTest { } DriverAndKeyConfigurator.configure(databaseManager) val testBindHelper = TestBindHelper(app) - val endpoint = StorageServiceManagerEndpoint(testBindHelper, this@runBlocking) + val endpoint = StorageServiceManagerEndpointImpl(testBindHelper, this@runBlocking) val e = assertFailsWith { endpoint.runGarbageCollection()