summaryrefslogtreecommitdiff
path: root/adservices/tests/cts/endtoends/topics
diff options
context:
space:
mode:
Diffstat (limited to 'adservices/tests/cts/endtoends/topics')
-rw-r--r--adservices/tests/cts/endtoends/topics/Android.bp5
-rw-r--r--adservices/tests/cts/endtoends/topics/AndroidTest.xml73
-rw-r--r--adservices/tests/cts/endtoends/topics/appupdate/Android.bp51
-rw-r--r--adservices/tests/cts/endtoends/topics/appupdate/AndroidManifest.xml30
-rw-r--r--adservices/tests/cts/endtoends/topics/appupdate/AndroidTest.xml85
-rw-r--r--adservices/tests/cts/endtoends/topics/appupdate/res/xml/ad_services_config.xml21
-rw-r--r--adservices/tests/cts/endtoends/topics/appupdate/src/com/android/adservices/tests/cts/topics/appupdate/AppUpdateTest.java (renamed from adservices/tests/cts/endtoends/topics/src/com/android/adservices/tests/cts/topics/AppUpdateTest.java)62
-rw-r--r--adservices/tests/cts/endtoends/topics/connection/Android.bp47
-rw-r--r--adservices/tests/cts/endtoends/topics/connection/AndroidManifest.xml30
-rw-r--r--adservices/tests/cts/endtoends/topics/connection/AndroidTest.xml62
-rw-r--r--adservices/tests/cts/endtoends/topics/connection/res/xml/ad_services_config.xml21
-rw-r--r--adservices/tests/cts/endtoends/topics/connection/src/com/android/adservices/tests/cts/topics/connection/TopicsConnectionTest.java207
-rw-r--r--adservices/tests/cts/endtoends/topics/mdd/Android.bp44
-rw-r--r--adservices/tests/cts/endtoends/topics/mdd/AndroidManifest.xml30
-rw-r--r--adservices/tests/cts/endtoends/topics/mdd/AndroidTest.xml59
-rw-r--r--adservices/tests/cts/endtoends/topics/mdd/res/xml/ad_services_config.xml19
-rw-r--r--adservices/tests/cts/endtoends/topics/mdd/src/com/android/adservices/tests/cts/topics/mdd/TopicsManagerMddTest.java284
-rw-r--r--adservices/tests/cts/endtoends/topics/src/com/android/adservices/tests/cts/topics/PreviewApiTest.java198
-rw-r--r--adservices/tests/cts/endtoends/topics/src/com/android/adservices/tests/cts/topics/TopicsManagerTest.java123
19 files changed, 1324 insertions, 127 deletions
diff --git a/adservices/tests/cts/endtoends/topics/Android.bp b/adservices/tests/cts/endtoends/topics/Android.bp
index e7047fc725..ce874443ae 100644
--- a/adservices/tests/cts/endtoends/topics/Android.bp
+++ b/adservices/tests/cts/endtoends/topics/Android.bp
@@ -39,12 +39,9 @@ android_test {
"general-tests",
"mts-adservices"
],
- data: [
- // Sample App will be installed and uninstalled in the test.
- ":CtsSampleTopicsApp1",
- ],
// To fix Pre-submit warning, suggested by farivar@
javacflags: ["-parameters"],
sdk_version: "module_current",
+ min_sdk_version: "Tiramisu",
test_mainline_modules: ["com.google.android.adservices.apex"],
}
diff --git a/adservices/tests/cts/endtoends/topics/AndroidTest.xml b/adservices/tests/cts/endtoends/topics/AndroidTest.xml
index 4e4b358a61..bb03e77815 100644
--- a/adservices/tests/cts/endtoends/topics/AndroidTest.xml
+++ b/adservices/tests/cts/endtoends/topics/AndroidTest.xml
@@ -15,42 +15,49 @@
~ limitations under the License.
-->
<configuration description="Config for Cts Ad Services E2E tests">
-<option name="test-suite-tag" value="cts" />
-<option name="test-tag" value="CtsAdServicesEndToEndTests" />
-<option name="config-descriptor:metadata" key="component" value="framework"/>
-<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
-<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
-<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+ <option name="test-suite-tag" value="cts" />
+ <option name="test-tag" value="CtsAdServicesEndToEndTests" />
+ <option name="config-descriptor:metadata" key="component" value="framework"/>
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
-<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="cleanup-apks" value="true"/>
- <!-- The test apps to be installed and uninstalled -->
- <option name="test-file-name" value="CtsAdServicesEndToEndTests.apk"/>
-</target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true"/>
+ <!-- The test apps to be installed and uninstalled -->
+ <option name="test-file-name" value="CtsAdServicesEndToEndTests.apk"/>
+ </target_preparer>
-<test class="com.android.tradefed.testtype.AndroidJUnitTest">
- <option name="hidden-api-checks" value="false" /> <!-- Allow hidden API uses -->
- <option name="package" value="com.android.adservices.tests.cts.endtoendtest"/>
-</test>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="hidden-api-checks" value="false" /> <!-- Allow hidden API uses -->
+ <option name="package" value="com.android.adservices.tests.cts.endtoendtest"/>
+ </test>
-<!-- Create place to store tests apks that will be installed/uninstalled in the test. -->
-<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="mkdir -p /data/local/tmp/cts/install" />
- <option name="teardown-command" value="rm -rf /data/local/tmp/cts"/>
- <!-- Uninstall the test app anyway in case failed test skips the uninstallation -->
- <option name="teardown-command"
- value="pm uninstall --user 0 com.android.adservices.tests.cts.topics.testapp1" />
-</target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.DeviceSetup" >
+ <option name="force-skip-system-props" value="true" />
+ <option name="disable-device-config-sync" value="true" />
+ </target_preparer>
-<!-- Push compiled APK file of test apps to a local place for installation -->
-<target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="push"
- value="CtsSampleTopicsApp1.apk->/data/local/tmp/cts/install/CtsSampleTopicsApp1.apk" />
-</target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <!-- Disable global/topics kill_switch to ignore the effect of actual PH values. -->
+ <option name="run-command" value="device_config put adservices global_kill_switch false" />
+ <option name="run-command" value="device_config put adservices topics_kill_switch false" />
+ <!-- Override Consent Manager to debug mode to grant user consent -->
+ <option name="run-command" value="setprop debug.adservices.consent_manager_debug_mode true" />
+ <option name="run-command" value="setprop log.tag.adservices VERBOSE" />
+ <!-- Override the flag to disable Topics enrollment check. -->
+ <option name="run-command" value="setprop debug.adservices.disable_topics_enrollment_check true" />
+ <!-- Forces using bundled model files. -->
+ <option name="run-command" value="device_config put adservices classifier_force_use_bundled_files true" />
-<object type="module_controller"
- class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
- <option name="mainline-module-package-name" value="com.google.android.adservices"/>
-</object>
-<option name="config-descriptor:metadata" key="mainline-param" value="com.google.android.adservices.apex" />
+ <option name="teardown-command" value="setprop debug.adservices.consent_manager_debug_mode false"/>
+ <option name="teardown-command" value="setprop debug.adservices.disable_topics_enrollment_check false" />
+ <option name="teardown-command" value="device_config put adservices classifier_force_use_bundled_files false" />
+ </target_preparer>
+
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+ <option name="mainline-module-package-name" value="com.google.android.adservices"/>
+ </object>
+ <option name="config-descriptor:metadata" key="mainline-param" value="com.google.android.adservices.apex" />
</configuration>
diff --git a/adservices/tests/cts/endtoends/topics/appupdate/Android.bp b/adservices/tests/cts/endtoends/topics/appupdate/Android.bp
new file mode 100644
index 0000000000..290e49c970
--- /dev/null
+++ b/adservices/tests/cts/endtoends/topics/appupdate/Android.bp
@@ -0,0 +1,51 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+ name: "CtsAdServicesTopicsAppUpdateTests",
+ srcs: [
+ "src/**/*.java",
+ ],
+ static_libs: [
+ "androidx.concurrent_concurrent-futures",
+ "compatibility-device-util-axt",
+ "truth-prebuilt",
+ "ub-uiautomator",
+ "adservices-test-fixtures",
+ "adservices-clients",
+ ],
+ libs: [
+ "android.test.base",
+ "framework-adservices.impl",
+ "framework-sdksandbox.impl",
+ ],
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-adservices"
+ ],
+ data: [
+ // Sample App will be installed and uninstalled in the test.
+ ":CtsSampleTopicsApp1",
+ ],
+ // To fix Pre-submit warning, suggested by farivar@
+ javacflags: ["-parameters"],
+ sdk_version: "module_current",
+ min_sdk_version: "Tiramisu",
+ test_mainline_modules: ["com.google.android.adservices.apex"],
+}
diff --git a/adservices/tests/cts/endtoends/topics/appupdate/AndroidManifest.xml b/adservices/tests/cts/endtoends/topics/appupdate/AndroidManifest.xml
new file mode 100644
index 0000000000..93c459781f
--- /dev/null
+++ b/adservices/tests/cts/endtoends/topics/appupdate/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.adservices.tests.cts.topics.appupdate" >
+
+ <uses-permission android:name="android.permission.ACCESS_ADSERVICES_TOPICS" />
+ <application>
+ <property android:name="android.adservices.AD_SERVICES_CONFIG"
+ android:resource="@xml/ad_services_config" />
+ </application>
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.adservices.tests.cts.topics.appupdate" >
+ </instrumentation>
+</manifest>
diff --git a/adservices/tests/cts/endtoends/topics/appupdate/AndroidTest.xml b/adservices/tests/cts/endtoends/topics/appupdate/AndroidTest.xml
new file mode 100644
index 0000000000..8b1b69139b
--- /dev/null
+++ b/adservices/tests/cts/endtoends/topics/appupdate/AndroidTest.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<configuration description="Config for Cts Ad Services App Update tests">
+ <option name="test-suite-tag" value="cts" />
+ <option name="test-tag" value="CtsAdServicesTopicsAppUpdateTests" />
+ <option name="config-descriptor:metadata" key="component" value="framework"/>
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true"/>
+ <!-- The test apps to be installed and uninstalled -->
+ <option name="test-file-name" value="CtsAdServicesTopicsAppUpdateTests.apk"/>
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="hidden-api-checks" value="false" /> <!-- Allow hidden API uses -->
+ <option name="package" value="com.android.adservices.tests.cts.topics.appupdate"/>
+ </test>
+
+ <target_preparer class="com.android.tradefed.targetprep.DeviceSetup" >
+ <option name="force-skip-system-props" value="true" />
+ <option name="disable-device-config-sync" value="true" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <!-- Disable global/topics kill_switch to ignore the effect of actual PH values. -->
+ <option name="run-command" value="device_config put adservices global_kill_switch false" />
+ <option name="run-command" value="device_config put adservices topics_kill_switch false" />
+ <!-- Override Consent Manager to debug mode to grant user consent -->
+ <option name="run-command" value="setprop debug.adservices.consent_manager_debug_mode true" />
+ <option name="run-command" value="setprop log.tag.adservices VERBOSE" />
+ <!-- Override the flag to disable Topics enrollment check. -->
+ <option name="run-command" value="setprop debug.adservices.disable_topics_enrollment_check true" />
+ <!-- Create place to store tests apks that will be installed/uninstalled in the test. -->
+ <option name="run-command" value="mkdir -p /data/local/tmp/cts/install" />
+ <!-- Forces using bundled model files. -->
+ <option name="run-command" value="device_config put adservices classifier_force_use_bundled_files true" />
+
+ <option name="teardown-command" value="setprop debug.adservices.consent_manager_debug_mode false"/>
+ <option name="teardown-command" value="setprop debug.adservices.disable_topics_enrollment_check false" />
+ <option name="teardown-command" value="device_config put adservices classifier_force_use_bundled_files false" />
+
+ <option name="teardown-command" value="rm -rf /data/local/tmp/cts"/>
+ <!-- Uninstall the test app anyway in case failed test skips the uninstallation -->
+ <option name="teardown-command"
+ value="pm uninstall --user 0 com.android.adservices.tests.cts.topics.testapp1" />
+ </target_preparer>
+
+ <!-- Create place to store tests apks that will be installed/uninstalled in the test. -->
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="mkdir -p /data/local/tmp/cts/install" />
+ <option name="teardown-command" value="rm -rf /data/local/tmp/cts"/>
+ <!-- Uninstall the test app anyway in case failed test skips the uninstallation -->
+ <option name="teardown-command"
+ value="pm uninstall --user 0 com.android.adservices.tests.cts.topics.testapp1" />
+ </target_preparer>
+
+ <!-- Push compiled APK file of test apps to a local place for installation -->
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="push"
+ value="CtsSampleTopicsApp1.apk->/data/local/tmp/cts/install/CtsSampleTopicsApp1.apk" />
+ </target_preparer>
+
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+ <option name="mainline-module-package-name" value="com.google.android.adservices"/>
+ </object>
+ <option name="config-descriptor:metadata" key="mainline-param" value="com.google.android.adservices.apex" />
+</configuration>
diff --git a/adservices/tests/cts/endtoends/topics/appupdate/res/xml/ad_services_config.xml b/adservices/tests/cts/endtoends/topics/appupdate/res/xml/ad_services_config.xml
new file mode 100644
index 0000000000..4524523557
--- /dev/null
+++ b/adservices/tests/cts/endtoends/topics/appupdate/res/xml/ad_services_config.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<ad-services-config>
+ <attribution allowAdPartnersToAccess="1234" allowAllToAccess="false" />
+ <custom-audiences allowAllToAccess="false" allowAdPartnersToAccess="1234, 4567" />
+ <topics allowAllToAccess="true" />
+</ad-services-config>
diff --git a/adservices/tests/cts/endtoends/topics/src/com/android/adservices/tests/cts/topics/AppUpdateTest.java b/adservices/tests/cts/endtoends/topics/appupdate/src/com/android/adservices/tests/cts/topics/appupdate/AppUpdateTest.java
index 033c951d59..0fe768b0d6 100644
--- a/adservices/tests/cts/endtoends/topics/src/com/android/adservices/tests/cts/topics/AppUpdateTest.java
+++ b/adservices/tests/cts/endtoends/topics/appupdate/src/com/android/adservices/tests/cts/topics/appupdate/AppUpdateTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.adservices.tests.cts.topics;
+package com.android.adservices.tests.cts.topics.appupdate;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
@@ -151,14 +151,17 @@ public class AppUpdateTest {
// not be used for epoch retrieval.
Thread.sleep(3 * TEST_EPOCH_JOB_PERIOD_MS);
- overridingBeforeTest();
+ overrideEpochPeriod(TEST_EPOCH_JOB_PERIOD_MS);
+ // We need to turn off random topic so that we can verify the returned topic.
+ overridePercentageForRandomTopic(TEST_TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC);
registerTopicResponseReceiver();
}
@After
public void tearDown() {
- overridingAfterTest();
+ overrideEpochPeriod(TOPICS_EPOCH_JOB_PERIOD_MS);
+ overridePercentageForRandomTopic(DEFAULT_TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC);
}
@Test
@@ -277,37 +280,6 @@ public class AppUpdateTest {
sContext.registerReceiver(mTopicsResponseReceiver, topicResponseIntentFilter);
}
- private void overridingBeforeTest() {
- overridingAdservicesLoggingLevel("VERBOSE");
-
- overrideDisableTopicsEnrollmentCheck("1");
- overrideEpochPeriod(TEST_EPOCH_JOB_PERIOD_MS);
-
- // We need to turn off random topic so that we can verify the returned topic.
- overridePercentageForRandomTopic(TEST_TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC);
-
- // We need to turn the Consent Manager into debug mode
- overrideConsentManagerDebugMode();
-
- // Turn off MDD to avoid model mismatching
- disableMddBackgroundTasks(true);
- }
-
- // Reset back the original values.
- private void overridingAfterTest() {
- overrideDisableTopicsEnrollmentCheck("0");
- overrideEpochPeriod(TOPICS_EPOCH_JOB_PERIOD_MS);
- overridePercentageForRandomTopic(DEFAULT_TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC);
- disableMddBackgroundTasks(false);
- overridingAdservicesLoggingLevel("INFO");
- }
-
- // Switch on/off for MDD service. Default value is false, which means MDD is enabled.
- private void disableMddBackgroundTasks(boolean isSwitchedOff) {
- ShellUtils.runShellCommand(
- "setprop debug.adservices.mdd_background_task_kill_switch " + isSwitchedOff);
- }
-
// Install test sample app 1 and verify the installation.
private void installTestSampleApp() {
String installMessage = ShellUtils.runShellCommand("pm install -r " + TEST_APK_PATH);
@@ -319,11 +291,10 @@ public class AppUpdateTest {
ShellUtils.runShellCommand("pm uninstall --user 0 " + TEST_PKG_NAME);
}
- // Override the flag to disable Topics enrollment check.
- private void overrideDisableTopicsEnrollmentCheck(String val) {
- // Setting it to 1 here disables the Topics enrollment check.
+ /** Forces JobScheduler to run the Epoch Computation job */
+ private void forceEpochComputationJob() {
ShellUtils.runShellCommand(
- "setprop debug.adservices.disable_topics_enrollment_check " + val);
+ "cmd jobscheduler run -f" + " " + ADSERVICES_PACKAGE_NAME + " " + EPOCH_JOB_ID);
}
// Override the Epoch Period to shorten the Epoch Length in the test.
@@ -339,17 +310,6 @@ public class AppUpdateTest {
+ overridePercentage);
}
- // Override the Consent Manager behaviour - Consent Given
- private void overrideConsentManagerDebugMode() {
- ShellUtils.runShellCommand("setprop debug.adservices.consent_manager_debug_mode true");
- }
-
- // Forces JobScheduler to run the Epoch Computation job.
- private void forceEpochComputationJob() {
- ShellUtils.runShellCommand(
- "cmd jobscheduler run -f" + " " + ADSERVICES_PACKAGE_NAME + " " + EPOCH_JOB_ID);
- }
-
// Forces JobScheduler to run the Maintenance job.
private void forceMaintenanceJob() {
ShellUtils.runShellCommand(
@@ -360,10 +320,6 @@ public class AppUpdateTest {
+ MAINTENANCE_JOB_ID);
}
- private void overridingAdservicesLoggingLevel(String loggingLevel) {
- ShellUtils.runShellCommand("setprop log.tag.adservices %s", loggingLevel);
- }
-
// Used to get the package name. Copied over from com.android.adservices.AndroidServiceBinder
private static String getAdServicesPackageName() {
final Intent intent = new Intent(TOPICS_SERVICE_NAME);
diff --git a/adservices/tests/cts/endtoends/topics/connection/Android.bp b/adservices/tests/cts/endtoends/topics/connection/Android.bp
new file mode 100644
index 0000000000..dbaaee2bc9
--- /dev/null
+++ b/adservices/tests/cts/endtoends/topics/connection/Android.bp
@@ -0,0 +1,47 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+ name: "CtsAdServicesTopicsConnectionTests",
+ srcs: [
+ "src/**/*.java",
+ ],
+ static_libs: [
+ "androidx.concurrent_concurrent-futures",
+ "compatibility-device-util-axt",
+ "truth-prebuilt",
+ "ub-uiautomator",
+ "adservices-test-fixtures",
+ "adservices-clients",
+ ],
+ libs: [
+ "android.test.base",
+ "framework-adservices.impl",
+ "framework-sdksandbox.impl",
+ ],
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-adservices"
+ ],
+ // To fix Pre-submit warning, suggested by farivar@
+ javacflags: ["-parameters"],
+ sdk_version: "module_current",
+ min_sdk_version: "Tiramisu",
+ test_mainline_modules: ["com.google.android.adservices.apex"],
+}
diff --git a/adservices/tests/cts/endtoends/topics/connection/AndroidManifest.xml b/adservices/tests/cts/endtoends/topics/connection/AndroidManifest.xml
new file mode 100644
index 0000000000..e23fe3ade4
--- /dev/null
+++ b/adservices/tests/cts/endtoends/topics/connection/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.adservices.tests.cts.topics.connection" >
+
+ <uses-permission android:name="android.permission.ACCESS_ADSERVICES_TOPICS" />
+ <application>
+ <property android:name="android.adservices.AD_SERVICES_CONFIG"
+ android:resource="@xml/ad_services_config" />
+ </application>
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.adservices.tests.cts.topics.connection" >
+ </instrumentation>
+</manifest>
diff --git a/adservices/tests/cts/endtoends/topics/connection/AndroidTest.xml b/adservices/tests/cts/endtoends/topics/connection/AndroidTest.xml
new file mode 100644
index 0000000000..a1f588a753
--- /dev/null
+++ b/adservices/tests/cts/endtoends/topics/connection/AndroidTest.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<configuration description="Config for Cts Ad Services Connection E2E tests">
+ <option name="test-suite-tag" value="cts" />
+ <option name="test-tag" value="CtsAdServicesTopicsConnectionTests" />
+ <option name="config-descriptor:metadata" key="component" value="framework"/>
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true"/>
+ <!-- The test apps to be installed and uninstalled -->
+ <option name="test-file-name" value="CtsAdServicesTopicsConnectionTests.apk"/>
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="hidden-api-checks" value="false" /> <!-- Allow hidden API uses -->
+ <option name="package" value="com.android.adservices.tests.cts.topics.connection"/>
+ </test>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <!-- Disable topics kill_switch to ignore the effect of actual PH values. -->
+ <option name="run-command" value="device_config put adservices topics_kill_switch false" />
+ <!-- Override Consent Manager to debug mode to grant user consent -->
+ <option name="run-command" value="setprop debug.adservices.consent_manager_debug_mode true" />
+ <option name="run-command" value="setprop log.tag.adservices VERBOSE" />
+ <!-- Override the flag to disable Topics enrollment check. -->
+ <option name="run-command" value="setprop debug.adservices.disable_topics_enrollment_check true" />
+ <!-- Forces using bundled model files. -->
+ <option name="run-command" value="device_config put adservices classifier_force_use_bundled_files true" />
+
+ <option name="teardown-command" value="setprop debug.adservices.consent_manager_debug_mode false"/>
+ <option name="teardown-command" value="setprop debug.adservices.disable_topics_enrollment_check false" />
+ <option name="teardown-command" value="device_config put adservices classifier_force_use_bundled_files false" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.DeviceSetup" >
+ <option name="force-skip-system-props" value="true" />
+ <option name="disable-device-config-sync" value="true" />
+ </target_preparer>
+
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+ <option name="mainline-module-package-name" value="com.google.android.adservices"/>
+ </object>
+ <option name="config-descriptor:metadata" key="mainline-param" value="com.google.android.adservices.apex" />
+</configuration>
diff --git a/adservices/tests/cts/endtoends/topics/connection/res/xml/ad_services_config.xml b/adservices/tests/cts/endtoends/topics/connection/res/xml/ad_services_config.xml
new file mode 100644
index 0000000000..4524523557
--- /dev/null
+++ b/adservices/tests/cts/endtoends/topics/connection/res/xml/ad_services_config.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<ad-services-config>
+ <attribution allowAdPartnersToAccess="1234" allowAllToAccess="false" />
+ <custom-audiences allowAllToAccess="false" allowAdPartnersToAccess="1234, 4567" />
+ <topics allowAllToAccess="true" />
+</ad-services-config>
diff --git a/adservices/tests/cts/endtoends/topics/connection/src/com/android/adservices/tests/cts/topics/connection/TopicsConnectionTest.java b/adservices/tests/cts/endtoends/topics/connection/src/com/android/adservices/tests/cts/topics/connection/TopicsConnectionTest.java
new file mode 100644
index 0000000000..077da0d1bd
--- /dev/null
+++ b/adservices/tests/cts/endtoends/topics/connection/src/com/android/adservices/tests/cts/topics/connection/TopicsConnectionTest.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.adservices.tests.cts.topics.connection;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+
+import android.adservices.clients.topics.AdvertisingTopicsClient;
+import android.adservices.topics.GetTopicsResponse;
+import android.adservices.topics.Topic;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.util.Log;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.compatibility.common.util.ShellUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+@RunWith(JUnit4.class)
+public class TopicsConnectionTest {
+ private static final String TAG = "TopicsConnectionTest";
+
+ private static final String ILLEGAL_STATE_EXCEPTION_ERROR_MESSAGE = "Service is not available.";
+
+ // The JobId of the Epoch Computation.
+ private static final int EPOCH_JOB_ID = 2;
+
+ // Override the Epoch Job Period to this value to speed up the epoch computation.
+ private static final long TEST_EPOCH_JOB_PERIOD_MS = 3000;
+
+ // Default Epoch Period.
+ private static final long TOPICS_EPOCH_JOB_PERIOD_MS = 7 * 86_400_000; // 7 days.
+
+ // Use 0 percent for random topic in the test so that we can verify the returned topic.
+ private static final int TEST_TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC = 0;
+ private static final int TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC = 5;
+
+ protected static final Context sContext = ApplicationProvider.getApplicationContext();
+ private static final Executor CALLBACK_EXECUTOR = Executors.newCachedThreadPool();
+
+ // Used to get the package name. Copied over from com.android.adservices.AdServicesCommon
+ private static final String TOPICS_SERVICE_NAME = "android.adservices.TOPICS_SERVICE";
+ private static final String ADSERVICES_PACKAGE_NAME = getAdServicesPackageName();
+
+ @Before
+ public void setup() throws Exception {
+ // We need to skip 3 epochs so that if there is any usage from other test runs, it will
+ // not be used for epoch retrieval.
+ Thread.sleep(3 * TEST_EPOCH_JOB_PERIOD_MS);
+
+ overrideEpochPeriod(TEST_EPOCH_JOB_PERIOD_MS);
+
+ // We need to turn off random topic so that we can verify the returned topic.
+ overridePercentageForRandomTopic(TEST_TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC);
+ }
+
+ @After
+ public void teardown() {
+ overrideEpochPeriod(TOPICS_EPOCH_JOB_PERIOD_MS);
+ overridePercentageForRandomTopic(TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC);
+ }
+
+ @Test
+ public void testEnableGlobalKillSwitch() throws Exception {
+ // First enable the Global Kill Switch and then connect to the TopicsService.
+ // The connection should fail with Exception.
+ enableGlobalKillSwitch(/* enabled */ true);
+
+ // Sdk1 calls the Topics git .
+ AdvertisingTopicsClient advertisingTopicsClient1 =
+ new AdvertisingTopicsClient.Builder()
+ .setContext(sContext)
+ .setSdkName("sdk1")
+ .setExecutor(CALLBACK_EXECUTOR)
+ .build();
+
+ // Due to global kill switch is enabled, we receive the IllegalStateException.
+ ExecutionException exception =
+ assertThrows(
+ ExecutionException.class, () -> advertisingTopicsClient1.getTopics().get());
+ assertThat(exception).hasCauseThat().isInstanceOf(IllegalStateException.class);
+ assertThat(exception).hasMessageThat().contains(ILLEGAL_STATE_EXCEPTION_ERROR_MESSAGE);
+
+ // Now disable the Global Kill Switch, we should be able to connect to the Service normally.
+ enableGlobalKillSwitch(/* enabled */ false);
+
+ // At beginning, Sdk1 receives no topic.
+ GetTopicsResponse sdk1Result = advertisingTopicsClient1.getTopics().get();
+ assertThat(sdk1Result.getTopics()).isEmpty();
+
+ // Now force the Epoch Computation Job. This should be done in the same epoch for
+ // callersCanLearnMap to have the entry for processing.
+ forceEpochComputationJob();
+
+ // Wait to the next epoch. We will not need to do this after we implement the fix in
+ // go/rb-topics-epoch-scheduling
+ Thread.sleep(TEST_EPOCH_JOB_PERIOD_MS);
+
+ // Since the sdk1 called the Topics API in the previous Epoch, it should receive some topic.
+ sdk1Result = advertisingTopicsClient1.getTopics().get();
+ assertThat(sdk1Result.getTopics()).isNotEmpty();
+
+ // We only have 1 test app which has 5 classification topics: 10147,10253,10175,10254,10333
+ // in the precomputed list.
+ // These 5 classification topics will become top 5 topics of the epoch since there is
+ // no other apps calling Topics API.
+ // The app will be assigned one random topic from one of these 5 topics.
+ assertThat(sdk1Result.getTopics()).hasSize(1);
+ Topic topic = sdk1Result.getTopics().get(0);
+
+ // topic is one of the 5 classification topics of the Test App.
+ assertThat(topic.getTopicId()).isIn(Arrays.asList(10147, 10253, 10175, 10254, 10333));
+
+ assertThat(topic.getModelVersion()).isAtLeast(1L);
+ assertThat(topic.getTaxonomyVersion()).isAtLeast(1L);
+ }
+
+ // Override global_kill_switch to ignore the effect of actual PH values.
+ // If enabled = true, override global_kill_switch to ON to turn off Adservices.
+ // If enabled = false, the AdServices is enabled.
+ private void enableGlobalKillSwitch(boolean enabled) {
+ String overrideString = enabled ? "true" : "false";
+ ShellUtils.runShellCommand("setprop debug.adservices.global_kill_switch " + overrideString);
+ }
+
+ // Override the Epoch Period to shorten the Epoch Length in the test.
+ private void overrideEpochPeriod(long overrideEpochPeriod) {
+ ShellUtils.runShellCommand(
+ "setprop debug.adservices.topics_epoch_job_period_ms " + overrideEpochPeriod);
+ }
+
+ // Override the Percentage For Random Topic in the test.
+ private void overridePercentageForRandomTopic(long overridePercentage) {
+ ShellUtils.runShellCommand(
+ "setprop debug.adservices.topics_percentage_for_random_topics "
+ + overridePercentage);
+ }
+
+ /** Forces JobScheduler to run the Epoch Computation job */
+ private void forceEpochComputationJob() {
+ ShellUtils.runShellCommand(
+ "cmd jobscheduler run -f" + " " + ADSERVICES_PACKAGE_NAME + " " + EPOCH_JOB_ID);
+ }
+
+ // Used to get the package name. Copied over from com.android.adservices.AndroidServiceBinder
+ private static String getAdServicesPackageName() {
+ final Intent intent = new Intent(TOPICS_SERVICE_NAME);
+ final List<ResolveInfo> resolveInfos =
+ sContext.getPackageManager()
+ .queryIntentServices(intent, PackageManager.MATCH_SYSTEM_ONLY);
+
+ if (resolveInfos == null || resolveInfos.isEmpty()) {
+ Log.e(
+ TAG,
+ "Failed to find resolveInfo for adServices service. Intent action: "
+ + TOPICS_SERVICE_NAME);
+ return null;
+ }
+
+ if (resolveInfos.size() > 1) {
+ Log.e(
+ TAG,
+ String.format(
+ "Found multiple services (%1$s) for the same intent action (%2$s)",
+ TOPICS_SERVICE_NAME, resolveInfos));
+ return null;
+ }
+
+ final ServiceInfo serviceInfo = resolveInfos.get(0).serviceInfo;
+ if (serviceInfo == null) {
+ Log.e(TAG, "Failed to find serviceInfo for adServices service");
+ return null;
+ }
+
+ return serviceInfo.packageName;
+ }
+}
diff --git a/adservices/tests/cts/endtoends/topics/mdd/Android.bp b/adservices/tests/cts/endtoends/topics/mdd/Android.bp
new file mode 100644
index 0000000000..3f7e5b9320
--- /dev/null
+++ b/adservices/tests/cts/endtoends/topics/mdd/Android.bp
@@ -0,0 +1,44 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+ name: "CtsAdServicesMddTests",
+ srcs: [
+ "src/**/*.java",
+ ],
+ static_libs: [
+ "androidx.concurrent_concurrent-futures",
+ "compatibility-device-util-axt", // Needed for ShellUtils.runShellCommand
+ "truth-prebuilt",
+ "adservices-clients",
+ ],
+ libs: [
+ "android.test.base",
+ // TODO(b/246590510): Remove these.
+ "framework-adservices.impl",
+ "framework-sdksandbox.impl",
+ ],
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-adservices"
+ ],
+ sdk_version: "module_current",
+ min_sdk_version: "Tiramisu",
+ test_mainline_modules: ["com.google.android.adservices.apex"],
+}
diff --git a/adservices/tests/cts/endtoends/topics/mdd/AndroidManifest.xml b/adservices/tests/cts/endtoends/topics/mdd/AndroidManifest.xml
new file mode 100644
index 0000000000..2cc1144184
--- /dev/null
+++ b/adservices/tests/cts/endtoends/topics/mdd/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.adservices.tests.cts.topics.mdd" >
+
+ <uses-permission android:name="android.permission.ACCESS_ADSERVICES_TOPICS" />
+ <application>
+ <property android:name="android.adservices.AD_SERVICES_CONFIG"
+ android:resource="@xml/ad_services_config" />
+ </application>
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.adservices.tests.cts.topics.mdd" >
+ </instrumentation>
+</manifest>
diff --git a/adservices/tests/cts/endtoends/topics/mdd/AndroidTest.xml b/adservices/tests/cts/endtoends/topics/mdd/AndroidTest.xml
new file mode 100644
index 0000000000..d5401029a9
--- /dev/null
+++ b/adservices/tests/cts/endtoends/topics/mdd/AndroidTest.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<configuration description="Config for Cts Ad Services MDD E2E tests">
+ <option name="test-suite-tag" value="cts" />
+ <option name="test-tag" value="CtsAdServicesMddTests" />
+ <option name="config-descriptor:metadata" key="component" value="framework"/>
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true"/>
+ <!-- The test apps to be installed and uninstalled -->
+ <option name="test-file-name" value="CtsAdServicesMddTests.apk"/>
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.adservices.tests.cts.topics.mdd"/>
+ </test>
+
+ <target_preparer class="com.android.tradefed.targetprep.DeviceSetup" >
+ <option name="force-skip-system-props" value="true" />
+ <option name="disable-device-config-sync" value="true" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <!-- Disable global/topics kill_switch to ignore the effect of actual PH values. -->
+ <option name="run-command" value="device_config put adservices global_kill_switch false" />
+ <option name="run-command" value="device_config put adservices topics_kill_switch false" />
+ <!-- Override Consent Manager to debug mode to grant user consent -->
+ <option name="run-command" value="setprop debug.adservices.consent_manager_debug_mode true" />
+ <option name="run-command" value="setprop log.tag.adservices VERBOSE" />
+ <!-- Override the flag to disable Topics enrollment check. -->
+ <option name="run-command" value="setprop debug.adservices.disable_topics_enrollment_check true" />
+
+ <option name="teardown-command" value="setprop debug.adservices.consent_manager_debug_mode false"/>
+ <option name="teardown-command" value="setprop debug.adservices.disable_topics_enrollment_check false" />
+ </target_preparer>
+
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+ <option name="mainline-module-package-name" value="com.google.android.adservices"/>
+ </object>
+ <option name="config-descriptor:metadata" key="mainline-param" value="com.google.android.adservices.apex" />
+</configuration>
diff --git a/adservices/tests/cts/endtoends/topics/mdd/res/xml/ad_services_config.xml b/adservices/tests/cts/endtoends/topics/mdd/res/xml/ad_services_config.xml
new file mode 100644
index 0000000000..d1ac060f67
--- /dev/null
+++ b/adservices/tests/cts/endtoends/topics/mdd/res/xml/ad_services_config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<ad-services-config>
+ <topics allowAllToAccess="true" />
+</ad-services-config>
diff --git a/adservices/tests/cts/endtoends/topics/mdd/src/com/android/adservices/tests/cts/topics/mdd/TopicsManagerMddTest.java b/adservices/tests/cts/endtoends/topics/mdd/src/com/android/adservices/tests/cts/topics/mdd/TopicsManagerMddTest.java
new file mode 100644
index 0000000000..8ee5a63cd2
--- /dev/null
+++ b/adservices/tests/cts/endtoends/topics/mdd/src/com/android/adservices/tests/cts/topics/mdd/TopicsManagerMddTest.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.adservices.tests.cts.topics;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.adservices.clients.topics.AdvertisingTopicsClient;
+import android.adservices.topics.GetTopicsResponse;
+import android.adservices.topics.Topic;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.util.Log;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.compatibility.common.util.ShellUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+@RunWith(JUnit4.class)
+public class TopicsManagerMddTest {
+ private static final String TAG = "TopicsManagerMddTest";
+ // The JobId of the Epoch Computation.
+ private static final int EPOCH_JOB_ID = 2;
+ // Job ID for Mdd Wifi Charging Task.
+ public static final int MDD_WIFI_CHARGING_PERIODIC_TASK_JOB_ID = 14;
+
+ // Override the Epoch Job Period to this value to speed up the epoch computation.
+ private static final long TEST_EPOCH_JOB_PERIOD_MS = 3000;
+ // Waiting time for assets to be downloaded after triggering MDD job.
+ private static final long TEST_MDD_DOWNLOAD_WAIT_TIME_MS = 10000;
+
+ // Default Epoch Period.
+ private static final long TOPICS_EPOCH_JOB_PERIOD_MS = 7 * 86_400_000; // 7 days.
+
+ // Classifier test constants.
+ private static final int TEST_CLASSIFIER_NUMBER_OF_TOP_LABELS = 5;
+ // Each app is given topics with a confidence score between 0.0 to 1.0 float value. This
+ // denotes how confident are you that a particular topic t1 is related to the app x that is
+ // classified.
+ // Threshold value for classifier confidence set to 0 to allow all topics and avoid filtering.
+ private static final float TEST_CLASSIFIER_THRESHOLD = 0.0f;
+ // classifier_type flag for ON_DEVICE_CLASSIFIER.
+ private static final int ON_DEVICE_CLASSIFIER = 1;
+ // Manifest file that points to CTS test assets:
+ // http://google3/wireless/android/adservices/mdd/topics_classifier/cts_test_1/
+ // These assets are have asset version set to 0 for verification in tests.
+ private static final String TEST_MDD_MANIFEST_FILE_URL =
+ "https://www.gstatic.com/mdi-serving/rubidium-adservices-topics-classifier/1043"
+ + "/784a7d30e5ac9fd6410fb017b05f392f67e9659a";
+
+ // Classifier default constants.
+ private static final int DEFAULT_CLASSIFIER_NUMBER_OF_TOP_LABELS = 3;
+ // Threshold value for classifier confidence set back to the default.
+ private static final float DEFAULT_CLASSIFIER_THRESHOLD = 0.1f;
+ // PRECOMPUTED_THEN_ON_DEVICE_CLASSIFIER
+ private static final int DEFAULT_CLASSIFIER_TYPE = 3;
+ private static final String DEFAULT_MDD_MANIFEST_FILE_URL =
+ "https://dl.google.com/mdi-serving/adservices/topics_classifier/manifest_configs/2"
+ + "/manifest_config_1661376643699.binaryproto";
+
+ // Use 0 percent for random topic in the test so that we can verify the returned topic.
+ private static final int TEST_TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC = 0;
+ private static final int TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC = 5;
+
+ protected static final Context sContext = ApplicationProvider.getApplicationContext();
+ private static final Executor CALLBACK_EXECUTOR = Executors.newCachedThreadPool();
+
+ // Used to get the package name. Copied over from com.android.adservices.AdServicesCommon
+ private static final String TOPICS_SERVICE_NAME = "android.adservices.TOPICS_SERVICE";
+ private static final String ADSERVICES_PACKAGE_NAME = getAdServicesPackageName();
+
+ @Before
+ public void setup() throws Exception {
+ // We need to skip 3 epochs so that if there is any usage from other test runs, it will
+ // not be used for epoch retrieval.
+ Thread.sleep(3 * TEST_EPOCH_JOB_PERIOD_MS);
+
+ overrideEpochPeriod(TEST_EPOCH_JOB_PERIOD_MS);
+ // We need to turn off random topic so that we can verify the returned topic.
+ overridePercentageForRandomTopic(TEST_TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC);
+ }
+
+ @After
+ public void teardown() {
+ overrideEpochPeriod(TOPICS_EPOCH_JOB_PERIOD_MS);
+ overridePercentageForRandomTopic(TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC);
+ }
+
+ @Test
+ public void testTopicsManager_downloadModelViaMdd_runOnDeviceClassifier() throws Exception {
+ // Set up test flags for on-device classification.
+ setupFlagsForOnDeviceClassifier();
+
+ // Override manifest URL for Mdd.
+ overrideMddManifestFileURL(TEST_MDD_MANIFEST_FILE_URL);
+ // Download assets via Mdd for testing.
+ triggerMddToDownload();
+ // Wait for 10 seconds for the assets to be downloaded.
+ Thread.sleep(TEST_MDD_DOWNLOAD_WAIT_TIME_MS);
+
+ // The Test App has 1 SDK: sdk1
+ // sdk1 calls the Topics API.
+ AdvertisingTopicsClient advertisingTopicsClient1 =
+ new AdvertisingTopicsClient.Builder()
+ .setContext(sContext)
+ .setSdkName("sdk1")
+ .setExecutor(CALLBACK_EXECUTOR)
+ .build();
+
+ // At beginning, Sdk1 receives no topic.
+ GetTopicsResponse sdk1Result = advertisingTopicsClient1.getTopics().get();
+ assertThat(sdk1Result.getTopics()).isEmpty();
+
+ // Now force the Epoch Computation Job. This should be done in the same epoch for
+ // callersCanLearnMap to have the entry for processing.
+ forceEpochComputationJob();
+
+ // Wait to the next epoch. We will not need to do this after we implement the fix in
+ // go/rb-topics-epoch-scheduling
+ Thread.sleep(TEST_EPOCH_JOB_PERIOD_MS);
+
+ // Since the sdk3 called the Topics API in the previous Epoch, it should receive some topic.
+ sdk1Result = advertisingTopicsClient1.getTopics().get();
+ assertThat(sdk1Result.getTopics()).isNotEmpty();
+
+ // We only have 5 topics classified by the on-device classifier.
+ // The app will be assigned one random topic from one of these 5 topics.
+ assertThat(sdk1Result.getTopics()).hasSize(1);
+ Topic topic = sdk1Result.getTopics().get(0);
+
+ // Top 5 classifications for empty string with v1 model are [10230, 10253, 10227, 10250,
+ // 10257]. This is
+ // computed by running the model on the device for empty string.
+ // topic is one of the 5 classification topics of the Test App.
+ List<Integer> expectedTopTopicIds = Arrays.asList(10230, 10253, 10227, 10250, 10257);
+ assertThat(topic.getTopicId()).isIn(expectedTopTopicIds);
+
+ // Verify assets are from the downloaded assets. These assets have asset version set to 0
+ // for verification.
+ // Test assets downloaded for CTS test:
+ // http://google3/wireless/android/adservices/mdd/topics_classifier/cts_test_1/
+ assertThat(topic.getModelVersion()).isAtLeast(0L);
+ assertThat(topic.getTaxonomyVersion()).isAtLeast(0L);
+
+ // Clean up test flags setup for on-device classification.
+ cleanupFlagsForOnDeviceClassifier();
+
+ // Reset Mdd manifest file url to default
+ overrideMddManifestFileURL(DEFAULT_MDD_MANIFEST_FILE_URL);
+ }
+
+ // Setup test flag values for on-device classifier.
+ private void setupFlagsForOnDeviceClassifier() {
+ // Set classifier flag to use on-device classifier.
+ overrideClassifierType(ON_DEVICE_CLASSIFIER);
+
+ // Set number of top labels returned by the on-device classifier to 5.
+ overrideClassifierNumberOfTopLabels(TEST_CLASSIFIER_NUMBER_OF_TOP_LABELS);
+ // Remove classifier threshold by setting it to 0.
+ overrideClassifierThreshold(TEST_CLASSIFIER_THRESHOLD);
+ }
+
+ // Reset test flags used for on-device classifier.
+ private void cleanupFlagsForOnDeviceClassifier() {
+ // Set classifier flag back to default.
+ overrideClassifierType(DEFAULT_CLASSIFIER_TYPE);
+
+ // Set number of top labels returned by the on-device classifier back to default.
+ overrideClassifierNumberOfTopLabels(DEFAULT_CLASSIFIER_NUMBER_OF_TOP_LABELS);
+ // Set classifier threshold back to default.
+ overrideClassifierThreshold(DEFAULT_CLASSIFIER_THRESHOLD);
+ }
+
+ // Override the flag to set manifest url for Mdd.
+ private void overrideMddManifestFileURL(String val) {
+ ShellUtils.runShellCommand(
+ "device_config put adservices mdd_topics_classifier_manifest_file_url " + val);
+ }
+
+ // Override the flag to select classifier type.
+ private void overrideClassifierType(int val) {
+ ShellUtils.runShellCommand("device_config put adservices classifier_type " + val);
+ }
+
+ // Override the flag to change the number of top labels returned by on-device classifier type.
+ private void overrideClassifierNumberOfTopLabels(int val) {
+ ShellUtils.runShellCommand(
+ "device_config put adservices classifier_number_of_top_labels " + val);
+ }
+
+ // Override the flag to change the threshold for the classifier.
+ private void overrideClassifierThreshold(float val) {
+ ShellUtils.runShellCommand("device_config put adservices classifier_threshold " + val);
+ }
+
+ // Override the Epoch Period to shorten the Epoch Length in the test.
+ private void overrideEpochPeriod(long overrideEpochPeriod) {
+ ShellUtils.runShellCommand(
+ "setprop debug.adservices.topics_epoch_job_period_ms " + overrideEpochPeriod);
+ }
+
+ // Override the Percentage For Random Topic in the test.
+ private void overridePercentageForRandomTopic(long overridePercentage) {
+ ShellUtils.runShellCommand(
+ "setprop debug.adservices.topics_percentage_for_random_topics "
+ + overridePercentage);
+ }
+
+ private void triggerMddToDownload() {
+ // Forces JobScheduler to run Mdd.
+ ShellUtils.runShellCommand(
+ "cmd jobscheduler run -f"
+ + " "
+ + ADSERVICES_PACKAGE_NAME
+ + " "
+ + MDD_WIFI_CHARGING_PERIODIC_TASK_JOB_ID);
+ }
+
+ /** Forces JobScheduler to run the Epoch Computation job */
+ private void forceEpochComputationJob() {
+ ShellUtils.runShellCommand(
+ "cmd jobscheduler run -f" + " " + ADSERVICES_PACKAGE_NAME + " " + EPOCH_JOB_ID);
+ }
+
+ // Used to get the package name. Copied over from com.android.adservices.AndroidServiceBinder
+ private static String getAdServicesPackageName() {
+ final Intent intent = new Intent(TOPICS_SERVICE_NAME);
+ final List<ResolveInfo> resolveInfos =
+ sContext.getPackageManager()
+ .queryIntentServices(intent, PackageManager.MATCH_SYSTEM_ONLY);
+
+ if (resolveInfos == null || resolveInfos.isEmpty()) {
+ Log.e(
+ TAG,
+ "Failed to find resolveInfo for adServices service. Intent action: "
+ + TOPICS_SERVICE_NAME);
+ return null;
+ }
+
+ if (resolveInfos.size() > 1) {
+ Log.e(
+ TAG,
+ String.format(
+ "Found multiple services (%1$s) for the same intent action (%2$s)",
+ TOPICS_SERVICE_NAME, resolveInfos));
+ return null;
+ }
+
+ final ServiceInfo serviceInfo = resolveInfos.get(0).serviceInfo;
+ if (serviceInfo == null) {
+ Log.e(TAG, "Failed to find serviceInfo for adServices service");
+ return null;
+ }
+
+ return serviceInfo.packageName;
+ }
+}
diff --git a/adservices/tests/cts/endtoends/topics/src/com/android/adservices/tests/cts/topics/PreviewApiTest.java b/adservices/tests/cts/endtoends/topics/src/com/android/adservices/tests/cts/topics/PreviewApiTest.java
new file mode 100644
index 0000000000..b3eff2dd81
--- /dev/null
+++ b/adservices/tests/cts/endtoends/topics/src/com/android/adservices/tests/cts/topics/PreviewApiTest.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.adservices.tests.cts.topics;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.adservices.clients.topics.AdvertisingTopicsClient;
+import android.adservices.topics.GetTopicsResponse;
+import android.adservices.topics.Topic;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.util.Log;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.compatibility.common.util.ShellUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+@RunWith(JUnit4.class)
+public class PreviewApiTest {
+ private static final String TAG = "PreviewApiTest";
+ // The JobId of the Epoch Computation.
+ private static final int EPOCH_JOB_ID = 2;
+
+ // Override the Epoch Job Period to this value to speed up the epoch computation.
+ private static final long TEST_EPOCH_JOB_PERIOD_MS = 3_000;
+
+ // Default Epoch Period.
+ private static final long TOPICS_EPOCH_JOB_PERIOD_MS = 7 * 86_400_000; // 7 days.
+
+ // Use 0 percent for random topic in the test so that we can verify the returned topic.
+ private static final int TEST_TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC = 0;
+ private static final int TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC = 5;
+
+ protected static final Context sContext = ApplicationProvider.getApplicationContext();
+ private static final Executor CALLBACK_EXECUTOR = Executors.newCachedThreadPool();
+
+ // Used to get the package name. Copied over from com.android.adservices.AdServicesCommon
+ private static final String TOPICS_SERVICE_NAME = "android.adservices.TOPICS_SERVICE";
+ private static final String ADSERVICES_PACKAGE_NAME = getAdServicesPackageName();
+
+ @Before
+ public void setup() throws Exception {
+ // We need to skip 3 epochs so that if there is any usage from other test runs, it will
+ // not be used for epoch retrieval.
+ Thread.sleep(3 * TEST_EPOCH_JOB_PERIOD_MS);
+
+ overrideEpochPeriod(TEST_EPOCH_JOB_PERIOD_MS);
+ // We need to turn off random topic so that we can verify the returned topic.
+ overridePercentageForRandomTopic(TEST_TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC);
+ }
+
+ @After
+ public void teardown() {
+ overrideEpochPeriod(TOPICS_EPOCH_JOB_PERIOD_MS);
+ overridePercentageForRandomTopic(TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC);
+ }
+
+ @Test
+ public void testRecordObservation() throws ExecutionException, InterruptedException {
+ // The Test app has 2 SDKs: sdk1 calls the Topics API. This will record the usage for Sdk1
+ // by default, recordObservation is true.
+ AdvertisingTopicsClient advertisingTopicsClient1 =
+ new AdvertisingTopicsClient.Builder()
+ .setContext(sContext)
+ .setSdkName("sdk1")
+ .setExecutor(CALLBACK_EXECUTOR)
+ .build();
+
+ // Sdk2 calls the Topics API and set the Record Observation to false. This will not record
+ // the usage for sdk2.
+ AdvertisingTopicsClient advertisingTopicsClient2 =
+ new AdvertisingTopicsClient.Builder()
+ .setContext(sContext)
+ .setSdkName("sdk2")
+ .setShouldRecordObservation(false)
+ .setExecutor(CALLBACK_EXECUTOR)
+ .build();
+
+ // At beginning, Sdk1 receives no topic.
+ GetTopicsResponse sdk1Result = advertisingTopicsClient1.getTopics().get();
+ assertThat(sdk1Result.getTopics()).isEmpty();
+
+ // At beginning, Sdk2 receives no topic.
+ GetTopicsResponse sdk2Result = advertisingTopicsClient2.getTopics().get();
+ assertThat(sdk2Result.getTopics()).isEmpty();
+
+ // Now force the Epoch Computation Job. This should be done in the same epoch for
+ // callersCanLearnMap to have the entry for processing.
+ forceEpochComputationJob();
+
+ // Wait to the next epoch. We will not need to do this after we implement the fix in
+ // go/rb-topics-epoch-scheduling
+ Thread.sleep(TEST_EPOCH_JOB_PERIOD_MS);
+
+ // Since the sdk1 called the Topics API in the previous Epoch, it should receive some topic.
+ sdk1Result = advertisingTopicsClient1.getTopics().get();
+ assertThat(sdk1Result.getTopics()).isNotEmpty();
+
+ // We only have 1 test app which has 5 classification topics: 10147,10253,10175,10254,10333
+ // in the precomputed list.
+ // These 5 classification topics will become top 5 topics of the epoch since there is
+ // no other apps calling Topics API.
+ // The app will be assigned one random topic from one of these 5 topics.
+ assertThat(sdk1Result.getTopics()).hasSize(1);
+ Topic topic = sdk1Result.getTopics().get(0);
+
+ // topic is one of the 5 classification topics of the Test App.
+ assertThat(topic.getTopicId()).isIn(Arrays.asList(10147, 10253, 10175, 10254, 10333));
+ assertThat(topic.getModelVersion()).isAtLeast(1L);
+ assertThat(topic.getTaxonomyVersion()).isAtLeast(1L);
+
+ // Sdk2 can not get any topics in this epoch because sdk2 sets not to record
+ // observation in previous epoch.
+ sdk2Result = advertisingTopicsClient2.getTopics().get();
+ assertThat(sdk2Result.getTopics()).isEmpty();
+ }
+
+ // Override the Epoch Period to shorten the Epoch Length in the test.
+ private void overrideEpochPeriod(long overrideEpochPeriod) {
+ ShellUtils.runShellCommand(
+ "setprop debug.adservices.topics_epoch_job_period_ms " + overrideEpochPeriod);
+ }
+
+ // Override the Percentage For Random Topic in the test.
+ private void overridePercentageForRandomTopic(long overridePercentage) {
+ ShellUtils.runShellCommand(
+ "setprop debug.adservices.topics_percentage_for_random_topics "
+ + overridePercentage);
+ }
+
+ /** Forces JobScheduler to run the Epoch Computation job */
+ private void forceEpochComputationJob() {
+ ShellUtils.runShellCommand(
+ "cmd jobscheduler run -f" + " " + ADSERVICES_PACKAGE_NAME + " " + EPOCH_JOB_ID);
+ }
+
+ // Used to get the package name. Copied over from com.android.adservices.AndroidServiceBinder
+ private static String getAdServicesPackageName() {
+ final Intent intent = new Intent(TOPICS_SERVICE_NAME);
+ final List<ResolveInfo> resolveInfos =
+ sContext.getPackageManager()
+ .queryIntentServices(intent, PackageManager.MATCH_SYSTEM_ONLY);
+
+ if (resolveInfos == null || resolveInfos.isEmpty()) {
+ Log.e(
+ TAG,
+ "Failed to find resolveInfo for adServices service. Intent action: "
+ + TOPICS_SERVICE_NAME);
+ return null;
+ }
+
+ if (resolveInfos.size() > 1) {
+ Log.e(
+ TAG,
+ String.format(
+ "Found multiple services (%1$s) for the same intent action (%2$s)",
+ TOPICS_SERVICE_NAME, resolveInfos));
+ return null;
+ }
+
+ final ServiceInfo serviceInfo = resolveInfos.get(0).serviceInfo;
+ if (serviceInfo == null) {
+ Log.e(TAG, "Failed to find serviceInfo for adServices service");
+ return null;
+ }
+
+ return serviceInfo.packageName;
+ }
+}
diff --git a/adservices/tests/cts/endtoends/topics/src/com/android/adservices/tests/cts/topics/TopicsManagerTest.java b/adservices/tests/cts/endtoends/topics/src/com/android/adservices/tests/cts/topics/TopicsManagerTest.java
index 40dbe05a91..b0eaf7ddc6 100644
--- a/adservices/tests/cts/endtoends/topics/src/com/android/adservices/tests/cts/topics/TopicsManagerTest.java
+++ b/adservices/tests/cts/endtoends/topics/src/com/android/adservices/tests/cts/topics/TopicsManagerTest.java
@@ -55,6 +55,23 @@ public class TopicsManagerTest {
// Default Epoch Period.
private static final long TOPICS_EPOCH_JOB_PERIOD_MS = 7 * 86_400_000; // 7 days.
+ // Classifier test constants.
+ private static final int TEST_CLASSIFIER_NUMBER_OF_TOP_LABELS = 5;
+ // Each app is given topics with a confidence score between 0.0 to 1.0 float value. This
+ // denotes how confident are you that a particular topic t1 is related to the app x that is
+ // classified.
+ // Threshold value for classifier confidence set to 0 to allow all topics and avoid filtering.
+ private static final float TEST_CLASSIFIER_THRESHOLD = 0.0f;
+ // ON_DEVICE_CLASSIFIER
+ private static final int TEST_CLASSIFIER_TYPE = 1;
+
+ // Classifier default constants.
+ private static final int DEFAULT_CLASSIFIER_NUMBER_OF_TOP_LABELS = 3;
+ // Threshold value for classifier confidence set back to the default.
+ private static final float DEFAULT_CLASSIFIER_THRESHOLD = 0.1f;
+ // PRECOMPUTED_THEN_ON_DEVICE_CLASSIFIER
+ private static final int DEFAULT_CLASSIFIER_TYPE = 3;
+
// Use 0 percent for random topic in the test so that we can verify the returned topic.
private static final int TEST_TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC = 0;
private static final int TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC = 5;
@@ -72,16 +89,20 @@ public class TopicsManagerTest {
// not be used for epoch retrieval.
Thread.sleep(3 * TEST_EPOCH_JOB_PERIOD_MS);
- overridingBeforeTest();
+ overrideEpochPeriod(TEST_EPOCH_JOB_PERIOD_MS);
+ // We need to turn off random topic so that we can verify the returned topic.
+ overridePercentageForRandomTopic(TEST_TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC);
}
@After
public void teardown() {
- overridingAfterTest();
+ overrideEpochPeriod(TOPICS_EPOCH_JOB_PERIOD_MS);
+ overridePercentageForRandomTopic(TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC);
}
@Test
- public void testTopicsManager() throws Exception {
+ public void testTopicsManager_runDefaultClassifier() throws Exception {
+ // Default classifier uses the precomputed list first, then on-device classifier.
// The Test App has 2 SDKs: sdk1 calls the Topics API and sdk2 does not.
// Sdk1 calls the Topics API.
AdvertisingTopicsClient advertisingTopicsClient1 =
@@ -116,7 +137,7 @@ public class TopicsManagerTest {
Topic topic = sdk1Result.getTopics().get(0);
// topic is one of the 5 classification topics of the Test App.
- assertThat(topic.getTopicId()).isIn(Arrays.asList(10147,10253,10175,10254,10333));
+ assertThat(topic.getTopicId()).isIn(Arrays.asList(10147, 10253, 10175, 10254, 10333));
assertThat(topic.getModelVersion()).isAtLeast(1L);
assertThat(topic.getTaxonomyVersion()).isAtLeast(1L);
@@ -133,41 +154,78 @@ public class TopicsManagerTest {
assertThat(sdk2Result2.getTopics()).isEmpty();
}
- private void overridingBeforeTest() {
- overridingAdservicesLoggingLevel("VERBOSE");
+ @Test
+ public void testTopicsManager_runOnDeviceClassifier() throws Exception {
+ // Set classifier flag to use on-device classifier.
+ overrideClassifierType(TEST_CLASSIFIER_TYPE);
+
+ // Set number of top labels returned by the on-device classifier to 5.
+ overrideClassifierNumberOfTopLabels(TEST_CLASSIFIER_NUMBER_OF_TOP_LABELS);
+ // Remove classifier threshold by setting it to 0.
+ overrideClassifierThreshold(TEST_CLASSIFIER_THRESHOLD);
+
+ // The Test App has 1 SDK: sdk3
+ // sdk3 calls the Topics API.
+ AdvertisingTopicsClient advertisingTopicsClient3 =
+ new AdvertisingTopicsClient.Builder()
+ .setContext(sContext)
+ .setSdkName("sdk3")
+ .setExecutor(CALLBACK_EXECUTOR)
+ .build();
- overrideDisableTopicsEnrollmentCheck("1");
- overrideEpochPeriod(TEST_EPOCH_JOB_PERIOD_MS);
+ // At beginning, Sdk3 receives no topic.
+ GetTopicsResponse sdk3Result = advertisingTopicsClient3.getTopics().get();
+ assertThat(sdk3Result.getTopics()).isEmpty();
- // We need to turn off random topic so that we can verify the returned topic.
- overridePercentageForRandomTopic(TEST_TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC);
+ // Now force the Epoch Computation Job. This should be done in the same epoch for
+ // callersCanLearnMap to have the entry for processing.
+ forceEpochComputationJob();
- // We need to turn the Consent Manager into debug mode
- overrideConsentManagerDebugMode();
+ // Wait to the next epoch. We will not need to do this after we implement the fix in
+ // go/rb-topics-epoch-scheduling
+ Thread.sleep(TEST_EPOCH_JOB_PERIOD_MS);
+
+ // Since the sdk3 called the Topics API in the previous Epoch, it should receive some topic.
+ sdk3Result = advertisingTopicsClient3.getTopics().get();
+ assertThat(sdk3Result.getTopics()).isNotEmpty();
+
+ // We only have 5 topics classified by the on-device classifier.
+ // The app will be assigned one random topic from one of these 5 topics.
+ assertThat(sdk3Result.getTopics()).hasSize(1);
+ Topic topic = sdk3Result.getTopics().get(0);
+
+ // Top 5 classifications for empty string with v2 model are [10230, 10253, 10227, 10250,
+ // 10257]. This is computed by running the model on the device for empty string.
+ // topic is one of the 5 classification topics of the Test App.
+ List<Integer> expectedTopTopicIds = Arrays.asList(10230, 10253, 10227, 10250, 10257);
+ assertThat(topic.getTopicId()).isIn(expectedTopTopicIds);
+
+ assertThat(topic.getModelVersion()).isAtLeast(2L);
+ assertThat(topic.getTaxonomyVersion()).isAtLeast(2L);
- // Turn off MDD to avoid model mismatching
- disableMddBackgroundTasks(true);
+ // Set classifier flag back to default.
+ overrideClassifierType(DEFAULT_CLASSIFIER_TYPE);
+
+ // Set number of top labels returned by the on-device classifier back to default.
+ overrideClassifierNumberOfTopLabels(DEFAULT_CLASSIFIER_NUMBER_OF_TOP_LABELS);
+ // Set classifier threshold back to default.
+ overrideClassifierThreshold(DEFAULT_CLASSIFIER_THRESHOLD);
}
- private void overridingAfterTest() {
- overrideDisableTopicsEnrollmentCheck("0");
- overrideEpochPeriod(TOPICS_EPOCH_JOB_PERIOD_MS);
- overridePercentageForRandomTopic(TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC);
- disableMddBackgroundTasks(false);
- overridingAdservicesLoggingLevel("INFO");
+ // Override the flag to select classifier type.
+ private void overrideClassifierType(int val) {
+ ShellUtils.runShellCommand("device_config put adservices classifier_type " + val);
}
- // Switch on/off for MDD service. Default value is false, which means MDD is enabled.
- private void disableMddBackgroundTasks(boolean isSwitchedOff) {
+ // Override the flag to change the number of top labels returned by on-device classifier type.
+ private void overrideClassifierNumberOfTopLabels(int val) {
ShellUtils.runShellCommand(
- "setprop debug.adservices.mdd_background_task_kill_switch " + isSwitchedOff);
+ "device_config put adservices classifier_number_of_top_labels " + val);
}
- // Override the flag to disable Topics enrollment check.
- private void overrideDisableTopicsEnrollmentCheck(String val) {
- // Setting it to 1 here disables the Topics' enrollment check.
- ShellUtils.runShellCommand(
- "setprop debug.adservices.disable_topics_enrollment_check " + val);
+ // Override the flag to change the threshold for the classifier.
+ private void overrideClassifierThreshold(float val) {
+ ShellUtils.runShellCommand("device_config put adservices classifier_threshold " + val);
}
// Override the Epoch Period to shorten the Epoch Length in the test.
@@ -183,21 +241,12 @@ public class TopicsManagerTest {
+ overridePercentage);
}
- // Override the Consent Manager behaviour - Consent Given
- private void overrideConsentManagerDebugMode() {
- ShellUtils.runShellCommand("setprop debug.adservices.consent_manager_debug_mode true");
- }
-
/** Forces JobScheduler to run the Epoch Computation job */
private void forceEpochComputationJob() {
ShellUtils.runShellCommand(
"cmd jobscheduler run -f" + " " + ADSERVICES_PACKAGE_NAME + " " + EPOCH_JOB_ID);
}
- private void overridingAdservicesLoggingLevel(String loggingLevel) {
- ShellUtils.runShellCommand("setprop log.tag.adservices %s", loggingLevel);
- }
-
// Used to get the package name. Copied over from com.android.adservices.AndroidServiceBinder
private static String getAdServicesPackageName() {
final Intent intent = new Intent(TOPICS_SERVICE_NAME);