From 47919591859d23d72686a18fd76e36f2320a3a70 Mon Sep 17 00:00:00 2001 From: Dave Snabel-Caunt Date: Mon, 9 Sep 2024 16:02:20 +0100 Subject: [PATCH] EUID Support for IMA Plugin --- .../src/main/AndroidManifest.xml | 3 + .../java/com/uid2/dev/IMADevApplication.kt | 20 ++++-- .../main/java/com/uid2/dev/MainActivity.java | 10 ++- .../main/java/com/uid2/dev/utils/BundleEx.kt | 7 ++ .../main/java/com/uid2/dev/utils/ContextEx.kt | 10 +++ .../com/uid2/dev/utils/PackageManagerEx.kt | 14 ++++ .../ima/EUIDSecureSignalsAdapter.kt | 70 +++++++++++++++++++ .../ima/EUIDSecureSignalsAdapterTest.kt | 29 ++++++++ 8 files changed, 157 insertions(+), 6 deletions(-) create mode 100644 securesignals-ima-dev-app/src/main/java/com/uid2/dev/utils/BundleEx.kt create mode 100644 securesignals-ima-dev-app/src/main/java/com/uid2/dev/utils/ContextEx.kt create mode 100644 securesignals-ima-dev-app/src/main/java/com/uid2/dev/utils/PackageManagerEx.kt create mode 100644 securesignals-ima/src/main/java/com/uid2/securesignals/ima/EUIDSecureSignalsAdapter.kt create mode 100644 securesignals-ima/src/test/java/com/uid2/securesignals/ima/EUIDSecureSignalsAdapterTest.kt diff --git a/securesignals-ima-dev-app/src/main/AndroidManifest.xml b/securesignals-ima-dev-app/src/main/AndroidManifest.xml index 13d22da..4852817 100644 --- a/securesignals-ima-dev-app/src/main/AndroidManifest.xml +++ b/securesignals-ima-dev-app/src/main/AndroidManifest.xml @@ -14,6 +14,9 @@ android:networkSecurityConfig="@xml/network_security_config" tools:ignore="UnusedAttribute"> + + + = Build.VERSION_CODES.TIRAMISU) { + @Suppress("WrongConstant") + getApplicationInfo(packageName, PackageManager.ApplicationInfoFlags.of(flags.toLong())) + } else { + @Suppress("DEPRECATION") + getApplicationInfo(packageName, flags) + } diff --git a/securesignals-ima/src/main/java/com/uid2/securesignals/ima/EUIDSecureSignalsAdapter.kt b/securesignals-ima/src/main/java/com/uid2/securesignals/ima/EUIDSecureSignalsAdapter.kt new file mode 100644 index 0000000..46c1eff --- /dev/null +++ b/securesignals-ima/src/main/java/com/uid2/securesignals/ima/EUIDSecureSignalsAdapter.kt @@ -0,0 +1,70 @@ +package com.uid2.securesignals.ima + +import android.content.Context +import com.google.ads.interactivemedia.v3.api.VersionInfo +import com.google.ads.interactivemedia.v3.api.signals.SecureSignalsAdapter +import com.google.ads.interactivemedia.v3.api.signals.SecureSignalsCollectSignalsCallback +import com.google.ads.interactivemedia.v3.api.signals.SecureSignalsInitializeCallback +import com.uid2.EUIDManager +import com.uid2.UID2 + +/** + * A custom exception type that is used to report failures from the EUIDSecureSignalsAdapter when an error has occurred. + */ +public class EUIDSecureSignalsException(message: String? = null, cause: Throwable? = null) : Exception(message, cause) + +/** + * An implementation of Google's IMA SecureSignalsAdapter that integrates UID2 tokens, accessed via the UID2Manager. + */ +public class EUIDSecureSignalsAdapter : SecureSignalsAdapter { + + /** + * Gets the version of the UID2 SDK. + */ + public override fun getSDKVersion(): VersionInfo = UID2.getVersionInfo().let { + VersionInfo(it.major, it.minor, it.patch) + } + + /** + * Gets the version of the UID2 Secure Signals plugin. + */ + public override fun getVersion(): VersionInfo = PluginVersion.getVersionInfo().let { + VersionInfo(it.major, it.minor, it.patch) + } + + /** + * Initialises the UID2 SDK with the given Context. + */ + public override fun initialize(context: Context, callback: SecureSignalsInitializeCallback) { + // It's possible that the EUIDManager is already initialised. If so, it's a no-op. + if (!EUIDManager.isInitialized()) { + EUIDManager.init(context) + } + + // After we've asked to initialize the manager, we should wait until it's complete before reporting success. + // This will potentially allow any previously persisted identity to be fully restored before we allow any + // signals to be collected. + EUIDManager.getInstance().addOnInitializedListener(callback::onSuccess) + } + + /** + * Collects the UID2 advertising token, if available. + */ + public override fun collectSignals(context: Context, callback: SecureSignalsCollectSignalsCallback) { + EUIDManager.getInstance().let { manager -> + val token = manager.getAdvertisingToken() + if (token != null) { + callback.onSuccess(token) + } else { + // We include the IdentityStatus in the "error" to have better visibility on why the Advertising Token + // was not present. There are a number of valid reasons why we don't have a token, but we are still + // required to report these as "failures". + callback.onFailure( + EUIDSecureSignalsException( + "No Advertising Token available (Status: ${manager.currentIdentityStatus.value})", + ), + ) + } + } + } +} diff --git a/securesignals-ima/src/test/java/com/uid2/securesignals/ima/EUIDSecureSignalsAdapterTest.kt b/securesignals-ima/src/test/java/com/uid2/securesignals/ima/EUIDSecureSignalsAdapterTest.kt new file mode 100644 index 0000000..2f2125e --- /dev/null +++ b/securesignals-ima/src/test/java/com/uid2/securesignals/ima/EUIDSecureSignalsAdapterTest.kt @@ -0,0 +1,29 @@ +package com.uid2.securesignals.ima + +import com.uid2.UID2 +import org.junit.Assert.assertEquals +import org.junit.Test + +class EUIDSecureSignalsAdapterTest { + @Test + fun `test SDK version`() { + val adapter = UID2SecureSignalsAdapter() + val version = adapter.sdkVersion + val expectedVersion = UID2.getVersionInfo() + + assertEquals(expectedVersion.major, version.majorVersion) + assertEquals(expectedVersion.minor, version.minorVersion) + assertEquals(expectedVersion.patch, version.microVersion) + } + + @Test + fun `test plugin version`() { + val adapter = UID2SecureSignalsAdapter() + val version = adapter.version + val expectedVersion = PluginVersion.getVersionInfo() + + assertEquals(expectedVersion.major, version.majorVersion) + assertEquals(expectedVersion.minor, version.minorVersion) + assertEquals(expectedVersion.patch, version.microVersion) + } +}