diff --git a/play-services-asterism/core/build.gradle b/play-services-asterism/core/build.gradle index e37fe498f4..dcc3c72c08 100644 --- a/play-services-asterism/core/build.gradle +++ b/play-services-asterism/core/build.gradle @@ -22,6 +22,7 @@ android { sourceSets { main.java.srcDirs += 'src/main/kotlin' + test.java.srcDirs += 'src/test/kotlin' } compileOptions { @@ -43,4 +44,6 @@ dependencies { implementation project(':play-services-base-core') implementation project(':play-services-constellation-core') + + testImplementation 'junit:junit:4.13.2' } diff --git a/play-services-asterism/core/src/main/kotlin/org/microg/gms/asterism/core/GetAsterismConsentHandler.kt b/play-services-asterism/core/src/main/kotlin/org/microg/gms/asterism/core/GetAsterismConsentHandler.kt index 415c40d1ab..28892aa529 100644 --- a/play-services-asterism/core/src/main/kotlin/org/microg/gms/asterism/core/GetAsterismConsentHandler.kt +++ b/play-services-asterism/core/src/main/kotlin/org/microg/gms/asterism/core/GetAsterismConsentHandler.kt @@ -16,10 +16,12 @@ import kotlinx.coroutines.withContext import org.microg.gms.constellation.core.ConstellationStateStore import org.microg.gms.constellation.core.RpcClient import org.microg.gms.constellation.core.authManager +import org.microg.gms.constellation.core.proto.AsterismClient import org.microg.gms.constellation.core.proto.Consent import org.microg.gms.constellation.core.proto.ConsentVersion import org.microg.gms.constellation.core.proto.DeviceID import org.microg.gms.constellation.core.proto.GetConsentRequest +import org.microg.gms.constellation.core.proto.GetConsentResponse import org.microg.gms.constellation.core.proto.RequestHeader import org.microg.gms.constellation.core.proto.RequestTrigger import org.microg.gms.constellation.core.proto.builder.buildRequestContext @@ -51,14 +53,10 @@ suspend fun handleGetAsterismConsent( ) ) - val gaiaConsent = response.gaia_consents.find { - it.asterism_client == request.asterismClient - } - val (consentValue, consentVersion) = if (gaiaConsent != null) { - gaiaConsent.consent to gaiaConsent.consent_version - } else { - Consent.NO_CONSENT to ConsentVersion.CONSENT_VERSION_UNSPECIFIED - } + val (consentValue, consentVersion) = resolveAsterismConsent( + response, + request.asterismClient + ) callbacks.onConsentFetched( Status.SUCCESS, @@ -85,6 +83,25 @@ suspend fun handleGetAsterismConsent( } } +internal fun resolveAsterismConsent( + response: GetConsentResponse, + asterismClient: AsterismClient +): Pair { + response.gaia_consents.firstOrNull { + it.asterism_client == asterismClient + }?.let { + return it.consent to it.consent_version + } + + if (asterismClient == AsterismClient.RCS) { + response.rcs_consent?.let { + return it.consent to it.consent_version + } + } + + return Consent.NO_CONSENT to ConsentVersion.CONSENT_VERSION_UNSPECIFIED +} + suspend fun handleGetIsPnvrConstellationDevice( context: Context, callbacks: IAsterismCallbacks diff --git a/play-services-asterism/core/src/test/kotlin/org/microg/gms/asterism/core/AsterismConsentResolverTest.kt b/play-services-asterism/core/src/test/kotlin/org/microg/gms/asterism/core/AsterismConsentResolverTest.kt new file mode 100644 index 0000000000..8a8081a8c6 --- /dev/null +++ b/play-services-asterism/core/src/test/kotlin/org/microg/gms/asterism/core/AsterismConsentResolverTest.kt @@ -0,0 +1,100 @@ +/* + * SPDX-FileCopyrightText: 2026 microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.asterism.core + +import org.junit.Assert.assertEquals +import org.junit.Test +import org.microg.gms.constellation.core.proto.AsterismClient +import org.microg.gms.constellation.core.proto.Consent +import org.microg.gms.constellation.core.proto.ConsentVersion +import org.microg.gms.constellation.core.proto.GaiaConsent +import org.microg.gms.constellation.core.proto.GetConsentResponse +import org.microg.gms.constellation.core.proto.RcsConsent + +class AsterismConsentResolverTest { + + @Test + fun matchingGaiaConsentTakesPrecedence() { + val response = GetConsentResponse( + rcs_consent = RcsConsent( + consent = Consent.CONSENTED, + consent_version = ConsentVersion.RCS_DEFAULT_ON_OUT_OF_BOX + ), + gaia_consents = listOf( + GaiaConsent( + asterism_client = AsterismClient.RCS, + consent = Consent.NO_CONSENT, + consent_version = ConsentVersion.RCS_CONSENT + ) + ) + ) + + assertEquals( + Consent.NO_CONSENT to ConsentVersion.RCS_CONSENT, + resolveAsterismConsent(response, AsterismClient.RCS) + ) + } + + @Test + fun rcsConsentIsUsedWhenMatchingGaiaConsentIsAbsent() { + val response = GetConsentResponse( + rcs_consent = RcsConsent( + consent = Consent.CONSENTED, + consent_version = ConsentVersion.RCS_DEFAULT_ON_OUT_OF_BOX + ) + ) + + assertEquals( + Consent.CONSENTED to ConsentVersion.RCS_DEFAULT_ON_OUT_OF_BOX, + resolveAsterismConsent(response, AsterismClient.RCS) + ) + } + + @Test + fun unrelatedGaiaConsentDoesNotMaskRcsConsent() { + val response = GetConsentResponse( + rcs_consent = RcsConsent( + consent = Consent.CONSENTED, + consent_version = ConsentVersion.RCS_CONSENT + ), + gaia_consents = listOf( + GaiaConsent( + asterism_client = AsterismClient.CONSTELLATION, + consent = Consent.NO_CONSENT, + consent_version = ConsentVersion.CONSENT_VERSION_UNSPECIFIED + ) + ) + ) + + assertEquals( + Consent.CONSENTED to ConsentVersion.RCS_CONSENT, + resolveAsterismConsent(response, AsterismClient.RCS) + ) + } + + @Test + fun rcsConsentIsNotAppliedToNonRcsClients() { + val response = GetConsentResponse( + rcs_consent = RcsConsent( + consent = Consent.CONSENTED, + consent_version = ConsentVersion.RCS_CONSENT + ) + ) + + assertEquals( + Consent.NO_CONSENT to ConsentVersion.CONSENT_VERSION_UNSPECIFIED, + resolveAsterismConsent(response, AsterismClient.CONSTELLATION) + ) + } + + @Test + fun noConsentDataFallsBackToNoConsent() { + assertEquals( + Consent.NO_CONSENT to ConsentVersion.CONSENT_VERSION_UNSPECIFIED, + resolveAsterismConsent(GetConsentResponse(), AsterismClient.RCS) + ) + } +}